表中有以下数据:
ID Category Value
1234 Cat01 V001
1234 Cat02 V002
1234 Cat03 V003
1234 Cat03 V004
1234 Cat03 V005
Run Code Online (Sandbox Code Playgroud)
我想要以下输出:
ID Cat01 Cat02 Cat03
1234 V001 V002 V003
1234 V001 V002 V004
1234 V001 V002 V005
Run Code Online (Sandbox Code Playgroud)
我想要实现的输出是一种数据透视表,其中我将所有值垂直放置在一个表中,并且我希望将这些值水平放置,并将类别作为列。但是有些类别具有多个值,在这种情况下,我需要重复所有其他类别的值并为每个重复值创建一行
如何在 PostgreSQL 中完成?
这是一个棘手的问题。对于每个row_name ,每个类别crosstab()
需要一个(或没有)值。
我们可以像这样解决这个限制:
SELECT id
, COALESCE(cat01, max(cat01) OVER w)
, COALESCE(cat02, max(cat02) OVER w)
, COALESCE(cat03, max(cat03) OVER w)
FROM crosstab(
'SELECT id::text || row_number() OVER (PARTITION BY id, category ORDER BY value) * -1 AS ext_id
, id, category, value
FROM tbl
ORDER BY ext_id, category, value'
,$$VALUES ('Cat01'::text), ('Cat02'), ('Cat03')$$
) AS ct (xid text, id int, cat01 text, cat02 text, cat03 text)
WINDOW w AS (PARTITION BY id);
Run Code Online (Sandbox Code Playgroud)
返回您想要的结果。
添加一个扩展的 id: ext_id
from the existingid
和一个行号,为相同的类别的每个值添加一个行号id
。通过这种方式,我们确保每个id
输入的行数与最常见类别的值一样多。我们得到一个这样的派生表来构建我们crosstab()
的:
SELECT id
, COALESCE(cat01, max(cat01) OVER w)
, COALESCE(cat02, max(cat02) OVER w)
, COALESCE(cat03, max(cat03) OVER w)
FROM crosstab(
'SELECT id::text || row_number() OVER (PARTITION BY id, category ORDER BY value) * -1 AS ext_id
, id, category, value
FROM tbl
ORDER BY ext_id, category, value'
,$$VALUES ('Cat01'::text), ('Cat02'), ('Cat03')$$
) AS ct (xid text, id int, cat01 text, cat02 text, cat03 text)
WINDOW w AS (PARTITION BY id);
Run Code Online (Sandbox Code Playgroud)
现在我们可以将它提供给crosstab()
使用安全的 2 参数形式来丢失属性。如果您对此不熟悉,请先阅读基础知识:
原件id
作为“额外列”结转。看:
你的问题留下了解释的空间。我的解决方案首先将每个类别的最低值配对,然后继续填充以下行,直到没有值为止。(我们可以以任何其他方式组合每个类别的多个值,它尚未定义。)如果一个类别缺少给定的值id
,其余的将用 NULL 值填充。
在最后一步中,我将这些 NULL 值替换为每个category
per的最大值id
:
COALESCE(cat01, max(cat01) OVER (PARTITION BY id, category))
Run Code Online (Sandbox Code Playgroud)
这实际上等同于:
max(cat01) OVER (PARTITION BY id, category)
Run Code Online (Sandbox Code Playgroud)
如果我们仅在值为 NULL 时默认使用窗口函数,我希望让它稍微快一点。
Raz*_*ici -2
您看到的是交叉表。假设您的表名为“Fact_Table”,请写入:
select * from crosstab('从 Fact_Table 中选择 id、类别、值')
如果您寻找其他变体,另请参阅http://www.postgresql.org/docs/9.5/static/tablefunc.html 。
归档时间: |
|
查看次数: |
14792 次 |
最近记录: |