PostgreSQL:熔化 table 并计算不同组的百分比

PostgreSQL: Melt table and calculate percentages for different groups

我正在尝试创建一个漏斗图,但我的数据现在是宽格式的。它有几个我想比较的组(例如,下面示例中的 AB),它们的比例不同,所以我想使用比例和原始值。

我的起始 table 看起来像这样:

| group | One | Two | Three |
|-------|-----|-----|-------|
|  A    | 100 | 75  | 50    |
|  B    | 10  | 7   | 6     |
|-------|-----|-----|-------|

我需要让 table 看起来像这样:

| group | stage | count | proportion of stage One |
|-------|-------|-------|-------------------------|
|  A    | One   | 100   | 1                       |
|  A    | Two   | 75    | 0.75                    |
|  A    | Three | 50    | 0.5                     |
|  B    | One   | 10    | 1                       |
|  B    | Two   | 7     | 0.7                     |
|  B    | Three | 6     | 0.6                     |
|-------|-------|-------|-------------------------|

该比例的计算方法是每行的值除以该组的最大值。第一阶段始终是 100%,然后第二阶段是该行的 count 除以该组值的最大值 count

我能做的最好的事情就是连接到 python 中的数据库并使用 Pandas 融化 table,但我真的很想将所有内容都保存在 [=31] 中=] 脚本.

我一直在摸索,零进度四太久了。非常感谢任何帮助。

您可以使用 UNION 查询来执行此操作,首先选择 One 的值,然后选择 TwoThree 并进行适当的除法以获得比例:

SELECT "group", 'One' AS stage, One, 1 AS proportion
FROM data
UNION ALL
SELECT "group", 'Two', Two, ROUND(1.0*Two/One, 2)
FROM data
UNION ALL
SELECT "group", 'Three', Three, ROUND(1.0*Three/One, 2)
FROM data
ORDER BY "group"

输出:

group   stage   one     proportion
A       One     100     1
A       Two     75      0.75
A       Three   50      0.50
B       One     10      1
B       Two     7       0.70
B       Three   6       0.60

Demo on dbfiddle

我推荐横向连接:

SELECT t."group", v.stage, v.count, v.count * 1.0 / t.one
FROM t CROSS JOIN LATERAL
     (VALUES ('One', one),
             ('Two', two),
             ('Three', three)
     ) v(stage, count);

对于少量数据,横向连接应该比 union all 快一点。随着数据变大,只扫描 table 一次是更大的胜利。然而,最大的胜利是当“table”确实是一个更复杂的查询时。那么lateral join在性能上可以明显好很多。