我如何在旋转时修复 PostgreSQL 中的不兼容错误?

How I fixed the incompatible error in PostgreSQL while pivoting?

我在 PostgreSQL 中旋转,但是当我 运行 查询时,输出显示:

ERROR:  return and sql tuple descriptions are incompatible
SQL state: 42601

总而言之,我想要原始的分销渠道、列中的年份和运营利润作为价值。

没有主元输出是:

dist_chann_name year operative_margin
1 2020 20783
1 2021 5791
2 2020 30362
3 2021 14501
3 2020 2765
3 2021 4535

这是我的查询:

SELECT *
FROM   crosstab(
'SELECT dist_chann_id, year, operative_margin
FROM marginality_by_channel
ORDER BY dist_chann_id, year'
     ) AS ct ("DC" int, "2020" int, "2021" int);

使用过滤聚合通常比有点复杂的 crosstab() 函数容易得多(至少在我看来是这样)。

select dist_chann_name as dc,
       sum(operative_margin) filter (where year = 2020) as "2020",
       sum(operative_margin) filter (where year = 2021) as "2021"
from marginality_by_channel
group by dist_chann_name
order by dist_chann_name;

错误消息的来源

其中一列没有您认为的数据类型。必须是operative_margin,可能是text?

crosstab() 的 1 参数形式仅使用 "category" 列(在您的示例中为 year)仅用于排序。 "row_name" 列(dist_chann_name - 或 dist_chann_id ?)会产生不同的错误消息。

解决方案

无论哪种方式,除非你能保证每个 "row_name" 恰好有两个值,否则使用 [= 的 2 参数形式更安全17=]:

SELECT *
FROM  crosstab(
   $$
   SELECT dist_chann_name, year, operative_margin
   FROM   marginality_by_channel
   ORDER  BY 1, 2
   $$
 , 'VALUES (2020), (2021)'
   ) AS ct ("DC" int, "2020" int, "2021" int);

db<>fiddle here

这个变体 碰巧 更能容忍类型不匹配(因为无论如何都以 text 传递)。参见:

  • PostgreSQL Crosstab Query

crosstab() 在许多结果值列中表现出色(更快、更短)。对于只有两个 "value" 列,聚合 FILTER 可能是更好(更简单)的选择。获得的性能不多(如果有的话,在增加一些开销之后)。参见:

  • 本题下

设置损坏

除此之外,您的设置一开始就含糊不清。它包括相同的两行 (dist_chann_name, year) = (3, 2021).

  • a_horse 在他的聚合 FILTER 解决方案中使用 sum()。您也可以使用 min()max(),或其他任何...
  • 我的 2 参数 形式的解决方案根据排序顺序输出 last 值。 (将其视为覆盖其专用位置的每个下一个值。)
  • 1-参数形式根据排序顺序输出第一个值。 (将其视为“先到先得”。多余的行将被丢弃。)

干净的解决方案将使用明确的排序顺序并记录效果,或者使用生成不同值的查询,或者将适当的聚合函数与 FILTER 解决方案一起使用。