我正在使用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
答案 0 :(得分:3)
你的第一个错误似乎很简单。根据{{1}}函数的第二个参数,crosstab()
必须作为第一个城市(按城市排序)。详细说明:
'Dubai'
和totalsales
的意外值代表每个totalamount
组第一行的值。 "额外"列被视为那样。详细说明:
要获得每name
的总和,请在聚合函数上运行窗口函数。详细说明:
name
更好的是,提供静态集作为第二个参数。输出列是硬编码的,动态生成数据列可能不可靠。如果你是一个新城市的另一排,这将会破裂 这样您也可以根据需要订购列。只需保持输出列和第二个参数同步。
答案 1 :(得分:0)
老实说,我认为你的数据库需要一些激烈的规范化,你的结果在几个列中(每个城市名称一个)不是我自己会做的。 然而,如果你想坚持下去,你可以这样做。
首先,您需要获得正确的金额。这样做的速度非常快:
select name, count(1) totalsales, sum(price) totalAmount
from products
group by name;
这将是您的结果:
NAME TOTALSALES TOTALAMOUNT
P2 3 6860
P1 3 2700
您可以通过这种方式获得产品/城市:
select name, city, count(1) totalCityName
from products
group by name, city
order by name, city;
结果:
NAME CITY TOTALCITYNAME
P1 London 1
P1 Melborun 1
P1 Moscow 1
P2 Dubai 1
P2 Munich 1
P2 Shunghai 1
如果您真的想要每个城市的列,您可以执行以下操作:
select name,
count(1) totalsales,
sum(price) totalAmount,
(select count(1)
from Products a
where a.City = 'London' and a.name = p.name) London,
...
from products p
group by name;
但我不推荐它! 这将是结果:
NAME TOTALSALES TOTALAMOUNT LONDON ...
P1 3 2700 1
P2 3 6860 0