Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 不带交叉表的透视表/tablefunc_Sql_Postgresql_Aggregate Functions_Crosstab_Aggregate Filter - Fatal编程技术网

Sql 不带交叉表的透视表/tablefunc

Sql 不带交叉表的透视表/tablefunc,sql,postgresql,aggregate-functions,crosstab,aggregate-filter,Sql,Postgresql,Aggregate Functions,Crosstab,Aggregate Filter,我有一张这样的桌子 输入 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

我有一张这样的桌子

输入

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
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
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
我希望能够以以下方式透视此表

输出

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
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
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
我能找到的所有文章都是基于第二列的在线数据透视表。我的最终目标是每个ID获得一条记录

最终输出

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
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
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

在这里,对大小、python、cpp和非代码列的值进行聚合。

使用条件聚合:

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
请参阅。
结果:


使用条件聚合:

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
请参阅。
结果:


您还可以使用名为tablefunc的PostgreSQL交叉表函数扩展。我建议您查看此链接(此处给出的示例与您想要的结果非常相似):

您还可以使用名为tablefunc的PostgreSQL交叉表函数扩展。我建议您查看此链接(此处给出的示例与您想要的结果非常相似):

当您希望避免使用
交叉表()
函数时,请使用aggregate
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;
这是使用聚合函数的最快方法。见:

为了获得绝对最佳的性能,
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);
同样的结果

dbfiddle-使用中间步骤

详细说明:

有关聚合函数(
sum(sum(size))上的窗口函数(…)
),请参阅:


请注意,如果同一个
id
应该有多个
作者,则会有一个细微的区别:在这种情况下,第一个查询返回多行,
crosstab()
变量只选择第一个作者。

如果要避免使用
crosstab()
函数,使用聚合
过滤器
子句可获得最佳性能和最清晰的代码:

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;
这是使用聚合函数的最快方法。见:

为了获得绝对最佳的性能,
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);
同样的结果

dbfiddle-使用中间步骤

详细说明:

有关聚合函数(
sum(sum(size))上的窗口函数(…)
),请参阅:


请注意,如果同一个
id
应该有多个
作者,则会有一个细微的区别:在这种情况下,第一个查询返回多行,而
crosstab()
变量只选择第一个作者。

您将所有可能的文件扩展名硬编码到查询中。如果您不知道所有可能的文件扩展名,有没有办法做到这一点?@djsosofresh Postgresql不支持(据我所知)动态数据透视。查看Mohamad答案中的链接以获得扩展功能。感谢您的回复。看起来Mohomad回答中提到的交叉表函数还需要定义输出列的名称和类型。您已经将所有可能的文件扩展名硬编码到查询中。如果您不知道所有可能的文件扩展名,有没有办法做到这一点?@djsosofresh Postgresql不支持(据我所知)动态数据透视。查看Mohamad答案中的链接以获得扩展功能。感谢您的回复。看起来Mohomad回答中提到的交叉表函数还需要定义输出列的名称和类型。