根据列的不同值创建列

问题描述 投票:0回答:1

我有一个包含许多不同产品的大型数据集。在小范围内,它看起来像这样:

产品 金额
AA 1 100
AA 1 150
AA 2 200
AA 2 120
BB 2 180
BB 2 220
抄送 3 80

我想以不同的顺序获取信息。写入与“产品”列中不同的值一样多的新列,然后用每月的金额总和填充它。它看起来像这样:

AA BB 抄送
1 250 不适用 不适用
2 320 400 不适用
3 不适用 不适用 80

重要的是对表格进行透视,这是我遇到的主要问题。我看到了类似的问题,但所有问题都已通过 PIVOT 函数解决,但我在 DBeaver 中使用 Postgres 数据库执行此操作,但它没有 PIVOT 函数:

SELECT *
FROM (
    SELECT product, month, amount
    FROM ventas
) AS SourceTable
PIVOT (
    SUM(amount)
    FOR month IN ([1], [2], [3])
) AS PivotTable;

SQL 错误 [42601]:错误:“PIVOT”处或附近的语法错误 位置:95

我尝试过不同的方法但没有成功。 我无法写出查询中所有产品的名称,因为太多了!

为了您的方便,这里有一个测试设置:

CREATE TABLE ventas (
    product VARCHAR(50),
    month INT,
    amount INT
);

INSERT INTO ventas (product, month, amount) VALUES 
('AA', 1, 100),
('AA', 1, 150),
('AA', 2, 200),
('AA', 2, 120),
('BB', 2, 180),
('BB', 2, 220),
('CC', 3, 80),
sql postgresql pivot-table dynamic-sql postgres-crosstab
1个回答
1
投票

如果您确实需要单独的输出列,唯一合理的方法是两步流程:

  1. 动态生成查询。
  2. 执行它。

如果您不熟悉

crosstab()
功能,请先阅读以下内容:

-- generate crosstab() query
SELECT format(
$f$  -- begin dynamic query string
SELECT * FROM crosstab(
   $q$
   SELECT month, product, sum(amount)
   FROM   ventas
   GROUP  BY 1, 2
   ORDER  BY 1, 2
   $q$
 , $c$VALUES (%s)$c$
   ) AS ct(month int, %s);
$f$  -- end dynamic query string
            , string_agg(quote_literal(sub.product), '), (')
            , string_agg(quote_ident  (sub.product), ' int, ') || ' int'
                 )
FROM  (SELECT DISTINCT product FROM ventas ORDER BY 1) sub;

这会生成以下形式的查询:

SELECT * FROM crosstab(
   $q$
   SELECT month, product, sum(amount)
   FROM   ventas
   GROUP  BY 1, 2
   ORDER  BY 1, 2
   $q$
 , $c$VALUES ('AA'), ('BB'), ('CC')$c$
   ) AS ct(month int, "AA" int, "BB" int, "CC" int);

...然后执行。

小提琴

密切相关,有更多解释和选项:

© www.soinside.com 2019 - 2024. All rights reserved.