根据多个其他列值选择列

时间:2020-02-11 11:24:11

标签: sql postgresql

我的表格如下-

id   p_id     Date        Tag
---------------------------------
1    1     11/02/2019     tag_1
2    1     12/02/2019     tag_2
3    7     20/01/2019     tag_3
4    1     13/02/2019     tag_2
5    8     25/11/2019     tag_1
6    7     26/02/2019     tag_4

我想从上面的表创建一个表,如下所示-

   p_id     Date_1    Date_2    Date_3
-----------------------------------------
   1     11/02/2019 12/02/2019 13/02/2019
   7     20/01/2019 26/02/2019 Null
   8     25/11/2019 Null       Null

必须使用以下逻辑创建该表:对于具有 tag_1,tag_3 的行,必须在Date_1列中获取日期,并且如果这些行具有 tag_2,tag_4 ,必须在Date_2 / Date_3列中获取日期。在这里,要注意的是,在上面的示例中,仅针对P_id = 1,我们使tag_2重复了两次。因此,如果 tag_2,tag_4 中的任何标签重复两次,则应在Date_3列中输入第二个日期,而应在Date_2列中输入第一个日期。

有什么建议吗? 谢谢!

2 个答案:

答案 0 :(得分:1)

如果要使用单独的列,则可以使用条件聚合:

select p_id,
       max(case when seqnum = 1 then date end) as date_1,
       max(case when seqnum = 2 then date end) as date_2,
       max(case when seqnum = 3 then date end) as date_3
from (select t.*,
             row_number() over (partition by p_id order by date) as seqnum
      from t
     ) t
group by p_id;

但是,如果您想收集列,我认为我建议使用数组而不是单独的列:

select p_id, array_agg(date order by date) as dates
from t
group by p_id;

您也可以将其扩展为您的格式:

select p_id,
       (array_agg(date order by date))[1] as date_1,
       (array_agg(date order by date))[2] as date_2,
       (array_agg(date order by date))[3] as date_3
from t
group by p_id;

答案 1 :(得分:1)

您可以尝试

select  p_id,
    max(case when rank = 1 then date end) date_1,
    max(case when rank = 2 then date end) date_2,
    max(case when rank = 3 then date end) date_3
from    (
select  t.*,rank() over (partition by t.p_id order by date) rank
from    table_name t
)t group by 1

FIDDLE DEMO