2017-11-25 131 views
0

我试图从string_agg在新列SQL基于结果

SELECT g.ganado_id, 
     string_agg(i.date, ', ') AS date 
FROM inseminacion i 
     INNER JOIN ganado g 
      ON g.ganado_id = i.ganado_id 
GROUP BY g.ganado_id 

实际输出

|ganado_id|date        | 
|1  |2016-10-15       | 
|2  |2016-10-15, 2017-02-15    | 
|3  |2016-10-15, 2017-03-09, 2017-05-27 | 
|4  |2017-06-02       | 

所需的输出添加日期数列添加

|ganado_id|date1  |date2  |date3  | 
|1  |2016-10-15 |   |   | 
|2  |2016-10-15 |2017-02-15 |   | 
|3  |2016-10-15 |2017-03-09 |2017-05-27 | 
|4  |2017-06-02 |   |   | 

我第一印象是使用数据透视表,但我不知道如何

+0

请张贴的数据在表格 – SEarle1986

回答

1

考虑不运行string_agg()但使用行号运行条件聚集:

WITH cte AS 
    (SELECT g.ganado_id, i.date, 
      ROW_NUMBER() OVER 
      (PARTITION BY g.ganado_id ORDER BY i.date) AS grp_num 
    FROM inseminacion i 
    INNER JOIN ganado g ON g.ganado_id = i.ganado_id) 

SELECT c.ganado_id 
     MAX(CASE WHEN c.grp_num = 1 THEN c.date ELSE NULL END) AS date1, 
     MAX(CASE WHEN c.grp_num = 2 THEN c.date ELSE NULL END) AS date2, 
     MAX(CASE WHEN c.grp_num = 3 THEN c.date ELSE NULL END) AS date3 
FROM cte c 
GROUP BY c.ganado_id 
+0

有没有办法隐藏列DATE3的情况下,所有的结果都为空?如果存在,还会显示额外的日期4? – danielctf

+0

您可以根据需要扩展MAX(...)行。至于隐藏/显示列,SQL是一种声明式的专用语言,其中列是结构组件,如这里所看到的那样是硬编码的。一旦声明被声明,它是不可变的。结果集不能根据数据更改列结构。行可以通过数据有条件地过滤。 – Parfait

0

你不需要两个表进行查询。 。 。换句话说,该join是没有必要的:

SELECT i.ganado_id, 
     MAX(i.date) FILTER (WHERE seqnum = 1) as date_1, 
     MAX(i.date) FILTER (WHERE seqnum = 2) as date_2, 
     MAX(i.date) FILTER (WHERE seqnum = 3) as date_3 
FROM (SELECT i.*, 
      ROW_NUMBER() OVER (PARTITION BY i.ganado_id ORDER BY i.date ASC) as seqnum 
     FROM inseminacion i 
    ) i 
GROUP BY i.ganado_id; 
+0

我认为如果'inseminacion'中有不在'ganado'中的记录,那么连接会在输出中产生变化。如果没有(只有OP知道这一点),那么我会同意你 – Hambone

+0

@Hambone。 。 。技术上是真的。但是这是一个合理的假设,称为'ganado_id'的字段将在两个表格之间匹配。 –

0

我知道你已经有一个答案,但对于谁可能有类似问题的其他人的利益,我想作为替代提供使用PostgreSQL的优阵列,这使得我很难回到使用任何其他DBMS的功能之一。

SELECT g.ganado_id, 
     array_agg(i.date) AS dates 
FROM inseminacion i 
     INNER JOIN ganado g 
      ON g.ganado_id = i.ganado_id 
GROUP BY g.ganado_id 

它本身可能实际上满足您的需求。它具有可扩展性更强的优势,所以如果你的数组超出了三个元素,你就不需要改变它。

另外,如果你需要将其转换为您列出的格式,这将是一个相对简单的任务:

with cte as (
    SELECT g.ganado_id, 
      array_agg(i.date) AS dates 
    FROM inseminacion i 
      INNER JOIN ganado g 
       ON g.ganado_id = i.ganado_id 
    GROUP BY g.ganado_id 
) 
select 
    ganado_id, dates[1], dates[2], dates[3] 
from cte 

,当然如果有一天,当你有一个第四和第五次约会,这将是那么容易,因为:

select 
    ganado_id, dates[1], dates[2], dates[3], dates[4], dates[5] 
from cte