[英]Pivot table without crosstab/tablefunc
I have a table like this我有一张这样的桌子
INPUT输入
id author size file_ext
--------------------------------
1 a 13661 python
1 a 13513 cpp
1 a 1211 non-code
2 b 1019 python
2 b 6881 cpp
2 b 1525 python
2 b 1208 non-code
3 c 1039 python
3 c 1299 cpp
I want to be able to pivot this table in the following manner我希望能够以下列方式旋转此表
OUTPUT输出
id author size python cpp non-code
-------------------------------------------------
1 a 13661 1 0 0
1 a 13513 0 1 0
1 a 1211 0 0 1
2 b 1019 1 0 0
2 b 6881 0 1 0
2 b 1525 1 0 0
2 b 1208 0 0 1
3 c 1039 1 0 0
3 c 1299 0 1 0
All the articles that I can find online pivot tables based on a second column.我可以根据第二列找到在线数据透视表的所有文章。 My ultimate goal is to get one records per ID.我的最终目标是为每个 ID 获取一条记录。
FINAL OUTPUT最终输出
id author size python cpp non-code
-------------------------------------------------
1 a 28385 1 1 1
2 b 10633 2 1 1
3 c 2338 1 1 0
Here the values of the size, python, cpp, non-code columns are aggregated.这里汇总了大小、python、cpp、非代码列的值。
With conditional aggregation:使用条件聚合:
select
id, author,
sum(size) size,
sum((file_ext = 'python')::int) python,
sum((file_ext = 'cpp')::int) cpp,
sum((file_ext = 'non-code')::int) "non-code"
from tablename
group by id, author
See the demo .请参阅演示。
Results:结果:
> id | author | size | python | cpp | non-code
> -: | :----- | ----: | -----: | --: | -------:
> 1 | a | 28385 | 1 | 1 | 1
> 2 | b | 10633 | 2 | 1 | 1
> 3 | c | 2338 | 1 | 1 | 0
While you want to avoid the crosstab()
function, use the aggregate FILTER
clause for best performance and clearest code:当您想避免使用crosstab()
函数时,请使用聚合FILTER
子句以获得最佳性能和最清晰的代码:
SELECT id, author
, sum(size) AS size
, count(*) FILTER (WHERE file_ext = 'python') AS python
, count(*) FILTER (WHERE file_ext = 'cpp') AS cpp
, count(*) FILTER (WHERE file_ext = 'non-code') AS "non-code"
FROM tablename
GROUP BY id, author;
That's the fastest way with just aggregate functions.这是仅使用聚合函数的最快方法。 See:看:
For absolute best performance, crosstab()
is typically faster - even though more verbose in this case:为了获得最佳性能, crosstab()
通常更快 - 即使在这种情况下更冗长:
SELECT id, author, size
, COALESCE(python , 0) AS python
, COALESCE(cpp , 0) AS cpp
, COALESCE("non-code", 0) AS "non-code"
FROM crosstab(
$$
SELECT id, author
, sum(sum(size)) OVER (PARTITION BY id) AS size
, file_ext
, count(*) AS ct
FROM tablename
GROUP BY id, author, file_ext
ORDER BY id, author, file_ext
$$
, $$VALUES ('python'), ('cpp'), ('non-code')$$
) AS (id int, author text, size numeric
, python int, cpp int, "non-code" int);
Same result.结果一样。
db<>fiddle here - with intermediary steps . db<> 在这里摆弄-有中间步骤。
Detailed explanation:详细解释:
For the window function over the aggregate function ( sum(sum(size)) OVER (...)
), see:对于聚合函数( sum(sum(size)) OVER (...)
)上的窗口函数,请参阅:
Note a subtle difference if there should be more than one author
for the same id
: while the first query returns multiple rows in this case, the crosstab()
variant just picks the first author.如果同一个id
应该有多个author
,请注意一个细微的区别:虽然在这种情况crosstab()
一个查询返回多行,但crosstab()
变体只选择第一作者。
You can also use the PostgreSQL crosstab function extension called tablefunc .您还可以使用名为tablefunc的 PostgreSQL 交叉表函数扩展。 I advise you to take a look at this link (the example given, there, is very similar to the result you want): https://vertabelo.com/blog/creating-pivot-tables-in-postgresql-using-the-crosstab-function/我建议您查看此链接(那里给出的示例与您想要的结果非常相似): https : //vertabelo.com/blog/creating-pivot-tables-in-postgresql-using-the -交叉表功能/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.