如何在特定条件下组合两行

时间:2018-04-16 18:00:07

标签: sql postgresql

我有以下表格:

CREATE table table1 (id int , cd date, ct TIME, co text)

INSERT INTO table1 
VALUES (0, '1/1/2018', '12:00:00', 'B'), 
        (1, '1/1/2018', '12:30:00', 'BC'), 
        (2, '1/12/2018', '12:00:00', 'B'), 
        (3, '1/22/2018', '12:00:00', 'BC')

当“cd”和“ct”列的值对于'B'和'BC'相同或者只有“ct”的值不同并且显示记录'B'的值时,我需要组合“co”列对于'B-BC'。 对于上面的表1记录,我需要以下结果:

"id"    "cd"    "ct"    "co"
"0" "1/1/2018"  "12:00:00 PM"   "B-BC"
"2" "1/12/2018" "12:00:00 PM"   "B"
"3" "1/22/2018" "12:00:00 PM"   "BC"

在postgresql 8.4中最有效的方法是什么?

2 个答案:

答案 0 :(得分:1)

我创建了两个公用表表达式(CTE)来提供将要组合的B和BC记录列表。逻辑是得到B记录和BC记录。然后执行从table1到cte_A表的左连接,并将join连接到cte_B表,但cte_b.id_del为null。这将删除cte_B中找到的id。最后,做一个何时对cte_A表中找到的id使用新的co值(B-BC)的情况。请参阅此处的演示:http://sqlfiddle.com/#!15/62caa/49

with cte_a as (select a.id as id_keep 
    from table1 a 
    inner join table1 b on a.cd=b.cd
     and a.co='B' and b.co='BC') 
,cte_b  as (select b.id as id_del 
    from table1 a 
    inner join table1 b on a.cd=b.cd
    and a.co='B' and b.co='BC')
select t1.id, 
       t1.cd, 
       t1.ct, 
       case when cte_a.id_keep is null 
            then t1.co 
            else 'B-BC' end as co 
from table1 t1
left join cte_a 
on t1.id=cte_a.id_keep
left join cte_b
on t1.id = cte_b.id_del
where cte_b.id_del is null;

答案 1 :(得分:0)

您可以使用string_agg

SELECT cd, MIN(id) AS id, min(ct) AS ct, string_agg(co, '-' ORDER BY ct) AS co
FROM table1
GROUP BY cd;

<强> DBFiddle Demo

修改

  

可爱的答案!但是对于&#39; B&#39;并不总是最低价值。我需要ct,这是专门记录在&#39; B&#39;,它可能更大&#39;&#39;对于BC&#39;或更少

您可以使用窗口函数:

WITH cte AS (
  SELECT *, ROW_NUMBER() OVER(PARTITION BY cd ORDER BY ct ASC) AS rn FROM table1
)
SELECT id, cd, ct,s.co
FROM cte
JOIN LATERAL(SELECT string_agg(co, '-' ORDER BY ct) AS co 
             FROM cte c2 WHERE c2.cd=cte.cd)s ON TRUE
WHERE rn=1;

<强> DBFiddle Demo2