具有更改行的 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;

这里是DBFiddle demo