具有更改行的 PostgreSQL 交叉表查询
PostgreSQL Crosstab Query With Changing Rows
有人可以帮我整理一下这个查询吗?
我有这个table:
store name status orders
billys store new 15
billys store ordered 20
billys store canceled 2
johnny store new 5
johnny store out_of_stock 20
rosie store new 6
rosie store ordered 4
rosie store out_of_stock 10
正如您所看到的,一些商店有一些其他商店没有的状态。
我想要的结果如下:
store name new ordered canceled out of stock
billys store 15 20 2 0
johnny store 5 0 0 20
rosie store 6 4 0 10
我试过以下方法:
SELECT * FROM crosstab(
'SELECT store_name::text as store_name,
status::text as status,
count(*)::int as orders
FROM organizations
INNER JOIN orders ON organization_id = organizations.id
GROUP BY store_name, status
ORDER BY store_name, status'
) x (store_name text, "new" int, "ordered" int)
但这不起作用,因为当新行不是预期值时它会中断。例如 'johnny store',在 'new' 不是 'ordered' 之后,它是 'out_of_stock',这样就不行了。
我浏览了一堆 Whosebug 帖子,但总的来说我还是很困惑。谢谢
我们可以使用 CASE 来避免使用 sub-queries。
CREATE TABLE organisation (
store_name VARCHAR(25),
status VARCHAR(25),
orders INT);
INSERT INTO organisation VALUES
('billys store', 'new' , 15),
('billys store', 'ordered' , 20),
('billys store', 'canceled' , 2),
('johnny store', 'new' , 5),
('johnny store', 'out_of_stock', 20),
('rosie store' , 'new' , 6),
('rosie store' , 'ordered' , 4),
('rosie store' , 'out_of_stock', 10);
8 行受影响
SELECT store_name,
SUM(CASE WHEN status='new' THEN orders ELSE 0 END) new_,
SUM(CASE WHEN status='canceled' THEN orders ELSE 0 END) canceled,
SUM(CASE WHEN status='ordered' THEN orders ELSE 0 END) ordered,
SUM(CASE WHEN status='new' THEN orders ELSE 0 END) o_o_s
FROM organisation o
GROUP BY store_name;
GO
store_name | new | canceled | ordered | o_o_s
:----------- | --: | -------: | ------: | ----:
billys store | 15 | 2 | 20 | 15
johnny store | 5 | 0 | 0 | 5
rosie store | 6 | 0 | 4 | 6
db<>fiddle here
也许您无法从我提供的 link 中理解它,但是 tablefunc 扩展使这更容易恕我直言。这是一个基于您的代码的示例,您可以将第一个查询替换为从您的表中获取数据的查询:
create temporary table myTable (storename text, status text, orders int);
insert into myTable (storename, status, orders)
values
('billys store','new', 15),
('billys store','ordered', 20),
('billys store','canceled', 2),
('johnny store','new', 5),
('johnny store','out_of_stock', 20),
('rosie store','new', 6),
('rosie store','ordered', 4),
('rosie store','out_of_stock', 10);
SELECT * FROM crosstab(
'SELECT storename,
status,
orders
FROM myTable',
'select * from unnest(string_to_array(''new,ordered,canceled,out_of_stock'', '',''))'
) x (storename text, "new" int, "ordered" int, "canceled" int, "out_of_stock" int);
drop table myTable;
有人可以帮我整理一下这个查询吗?
我有这个table:
store name status orders
billys store new 15
billys store ordered 20
billys store canceled 2
johnny store new 5
johnny store out_of_stock 20
rosie store new 6
rosie store ordered 4
rosie store out_of_stock 10
正如您所看到的,一些商店有一些其他商店没有的状态。
我想要的结果如下:
store name new ordered canceled out of stock
billys store 15 20 2 0
johnny store 5 0 0 20
rosie store 6 4 0 10
我试过以下方法:
SELECT * FROM crosstab(
'SELECT store_name::text as store_name,
status::text as status,
count(*)::int as orders
FROM organizations
INNER JOIN orders ON organization_id = organizations.id
GROUP BY store_name, status
ORDER BY store_name, status'
) x (store_name text, "new" int, "ordered" int)
但这不起作用,因为当新行不是预期值时它会中断。例如 'johnny store',在 'new' 不是 'ordered' 之后,它是 'out_of_stock',这样就不行了。
我浏览了一堆 Whosebug 帖子,但总的来说我还是很困惑。谢谢
我们可以使用 CASE 来避免使用 sub-queries。
CREATE TABLE organisation ( store_name VARCHAR(25), status VARCHAR(25), orders INT); INSERT INTO organisation VALUES ('billys store', 'new' , 15), ('billys store', 'ordered' , 20), ('billys store', 'canceled' , 2), ('johnny store', 'new' , 5), ('johnny store', 'out_of_stock', 20), ('rosie store' , 'new' , 6), ('rosie store' , 'ordered' , 4), ('rosie store' , 'out_of_stock', 10);
8 行受影响
SELECT store_name, SUM(CASE WHEN status='new' THEN orders ELSE 0 END) new_, SUM(CASE WHEN status='canceled' THEN orders ELSE 0 END) canceled, SUM(CASE WHEN status='ordered' THEN orders ELSE 0 END) ordered, SUM(CASE WHEN status='new' THEN orders ELSE 0 END) o_o_s FROM organisation o GROUP BY store_name; GO
store_name | new | canceled | ordered | o_o_s :----------- | --: | -------: | ------: | ----: billys store | 15 | 2 | 20 | 15 johnny store | 5 | 0 | 0 | 5 rosie store | 6 | 0 | 4 | 6
db<>fiddle here
也许您无法从我提供的 link 中理解它,但是 tablefunc 扩展使这更容易恕我直言。这是一个基于您的代码的示例,您可以将第一个查询替换为从您的表中获取数据的查询:
create temporary table myTable (storename text, status text, orders int);
insert into myTable (storename, status, orders)
values
('billys store','new', 15),
('billys store','ordered', 20),
('billys store','canceled', 2),
('johnny store','new', 5),
('johnny store','out_of_stock', 20),
('rosie store','new', 6),
('rosie store','ordered', 4),
('rosie store','out_of_stock', 10);
SELECT * FROM crosstab(
'SELECT storename,
status,
orders
FROM myTable',
'select * from unnest(string_to_array(''new,ordered,canceled,out_of_stock'', '',''))'
) x (storename text, "new" int, "ordered" int, "canceled" int, "out_of_stock" int);
drop table myTable;