我有一张巨大的桌子,看起来像这样
Group | Code | Value
------|------|------
G1 |0 |V1
G1 |2 |V2
G1 |2 |V3
G1 |1 |V4
G1 |2 |V5
G1 |2 |V6
G2 |0 |V7
G2 |1 |V8
G2 |1 |V9
G2 |2 |V10
G2 |2 |V11
G2 |2 |V12
G2 |2 |V13
我需要生成一个像这样的表
Group | Code | Value
------|------|------
G1 |0 |V1
G1 |2 |V2+V3
G1 |1 |V4
G1 |2 |V5+V6
G2 |0 |V7
G2 |1 |V8
G2 |1 |V9
G2 |2 |V10+V11
G2 |2 |V12+V13
值code = 2
始终显示为一对,我需要总结两个连续的code = 2
值。有关如何使用SQL语句而不是存储过程的任何想法?任何可以帮助我做到这一点的特殊功能。我正在尝试Postgres 9.6谢谢。
答案 0 :(得分:1)
我假设您希望按Value
列的数字部分对行进行排序。如果我们在表格中调用t
,那么这是一个使用窗口函数执行所需操作的查询:
SELECT "group", code, string_agg(value, '+')
FROM
(SELECT *, (row_number() OVER (PARTITION BY "group", code ORDER BY n) - 1) / CASE code WHEN 2 THEN 2 ELSE 1 END AS code_group
FROM (SELECT *,substr(value,2)::integer AS n FROM t) t1
) t2
GROUP BY "group", code, code_group
ORDER BY min(n);
我们的想法是首先提取(在子查询中)value
的数字部分,以便我们以后可以将其用作排序键。然后我们使用以下复杂的表达:
(row_number() OVER (PARTITION BY "group", code ORDER BY n) - 1) / CASE code WHEN 2 THEN 2 ELSE 1 END
这基本上分配给每组行(按group
,code
分组)从0开始的递增数字。因此第一行为0,下一行为1,依此类推。但是有一个例外。如果code
是2,那么我们使用以下编号方案:0,0,1,1,2,2 ......这是通过将行号除以2来实现的。我称这个数字为code_group
。在最后一步中,我们按group
,code
(与之前一样)进行分组,但也code_group
分组,以便将带有code=2
的连续行对合并为一对。
答案 1 :(得分:1)
select *
from (
select
grp, code,
case when code = 2 then
case when rn & 1 = 1 then null
else concat(lag(value) over w, '+', value)
end
else value
end as value
from (
select *, row_number() over w rn
from a_table
window w as (partition by code order by grp, code)
) s
window w as (order by grp, code, rn)
) s
where value notnull
order by grp, code
步骤: