sql - 使用 PostgreSQL 的交叉表查询中的计数和总和无效

标签 sql postgresql postgresql-9.3 crosstab window-functions

我使用的是 PostgreSQL 9.3 版本的数据库。

我有一种情况,我想计算产品销售数量并对产品数量求和,还想在产品销售的列中显示城市。

例子

设置

create table products (
 name varchar(20),
 price integer,
 city varchar(20)
);

insert into products values
   ('P1',1200,'London'),
   ('P1',100,'Melborun'),
   ('P1',1400,'Moscow'),
   ('P2',1560,'Munich'),
   ('P2',2300,'Shunghai'),
   ('P2',3000,'Dubai');

交叉表查询:

select * from crosstab (
        'select  name,count(*),sum(price),city,count(city)
         from products
         group by  name,city
         order by  name,city
         '
        ,           
        'select distinct city from products order by 1'
     ) 
     as tb (
         name varchar(20),TotalSales bigint,TotalAmount bigint,London bigint,Melborun bigint,Moscow bigint,Munich bigint,Shunghai bigint,Dubai bigint
     );

输出

name    totalsales  totalamount     london     melborun    moscow      munich    shunghai    dubai  
---------------------------------------------------------------------------------------------------------
 P1         1           1200                       1          1            1 
 P2         1           3000          1                                               1         1

预期输出:

name    totalsales  totalamount     london     melborun    moscow      munich    shunghai    dubai  
---------------------------------------------------------------------------------------------------------
 P1         3           2700           1          1           1               
 P2         3           6860                                               1          1         1        

最佳答案

您的第一个错误似乎很简单。根据 crosstab() 函数的第二个参数,'Dubai' 必须作为第一个城市(按城市排序)。详情:

totalsalestotalamount 的意外值表示每个 name 组第一行的值。 “额外”列被这样对待。详情:

要获取每个 name 的总和,请在聚合函数上运行窗口函数。详情:

select * from crosstab (
   'select name
          ,sum(count(*))   OVER (PARTITION BY name)
          ,sum(sum(price)) OVER (PARTITION BY name)
          ,city
          ,count(city)
    from   products
    group  by name,city
    order  by name,city
    '
--  ,'select distinct city from products order by 1' -- replaced
    ,$$SELECT unnest('{Dubai,London,Melborun
                      ,Moscow,Munich,Shunghai}'::varchar[])$$
) AS tb (
    name varchar(20), TotalSales bigint, TotalAmount bigint
   ,Dubai bigint
   ,London bigint
   ,Melborun bigint
   ,Moscow bigint
   ,Munich bigint
   ,Shunghai bigint
   );

更好的是,提供一个静态集作为第二个参数。输出列是硬编码的,动态生成数据列可能不可靠。如果你在新城市的另一行,这将中断。
通过这种方式,您还可以根据需要对列进行排序。只需保持输出列和第二个参数同步。

关于sql - 使用 PostgreSQL 的交叉表查询中的计数和总和无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28562244/

相关文章:

sql - 运行查询并在TEdit中显示结果

postgresql - 我应该在 PostgreSQL 数据库中选择哪种时间戳类型?

Postgresql 在尝试使用音量时引发 'data directory has wrong ownership'

json - 向 Postgres 查询 JSON 中的项目数

arrays - 将数组的数组作为参数传递给函数

sql - 在 SQL 中计算文档频率

mysql - 合并两个使用不同时间范围的最小/最大/平均值查询

javascript - ASP.NET MVC JSON Entity Framework - 保存数据

Mysql查询返回基于同一表中多列的行

sql - 如何在postgresql中按用户组选择