无法在 Postgres 交叉表查询中使用通用表表达式

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

我正在尝试使用 Postgres 的

tablefunc
扩展的
CROSSTAB
函数对某些数据执行透视操作。数据首先需要进行一些转换,我在一些通用表表达式中执行。

但是,似乎

CROSSTAB
看不到这些表达式的结果。

例如,此查询从临时表获取数据效果很好:

CREATE EXTENSION IF NOT EXISTS tablefunc;
CREATE TEMPORARY TABLE
  temporary_table
    (name, category, category_value)
ON COMMIT DROP
AS (
  VALUES
    ('A',  'foo',    1             ),
    ('A',  'bar',    2             ),
    ('B',  'foo',    3             ),
    ('B',  'bar',    4             )
);

SELECT * FROM
  CROSSTAB(
    'SELECT * FROM temporary_table',
    $$
      VALUES
        ('foo'),
        ('bar')
    $$
  ) AS (
    name TEXT,
    foo  INT,
    bar  INT
  );

并且如预期的那样,产生以下输出:

名字 酒吧
A 1 2
B 3 4

但是同样的查询,这次使用通用表表达式不会运行:

CREATE EXTENSION IF NOT EXISTS tablefunc;
WITH
  common_table
    (name, category, category_value)
AS (
  VALUES
    ('A',  'foo',    1             ),
    ('A',  'bar',    2             ),
    ('B',  'foo',    3             ),
    ('B',  'bar',    4             )
)
SELECT * FROM
  CROSSTAB(
    'SELECT * FROM common_table',
    $$
      VALUES
        ('foo'),
        ('bar')
    $$
  ) AS (
    name TEXT,
    foo  INT,
    bar  INT
  )

并产生以下错误:

ERROR:  relation "common_table" does not exist
LINE 1: SELECT * FROM common_table
                      ^
QUERY:  SELECT * FROM common_table

********** Error **********

ERROR: relation "common_table" does not exist
SQL state: 42P01

我认为这意味着文本查询

SELECT * FROM common_table
在某种不同的上下文中运行。我该如何让它发挥作用?

sql postgresql pivot pivot-table temp-tables
1个回答
13
投票

您需要做的就是将字符串内的

CTE
作为第一个参数移动到
crosstab(text, text)
函数,就像使用 select 语句一样。它将被正确解析并执行。这是因为您提供了完整的 SQL 语句,该语句在第一个参数中生成源集。

您需要在字符串内加倍引号或使用美元引号

$$
就像您对第二个参数所做的那样,我在下面所做的:

SELECT * FROM
  CROSSTAB(
    $$
    WITH common_table(name, category, category_value) AS (
      VALUES
        ('A',  'foo',    1             ),
        ('A',  'bar',    2             ),
        ('B',  'foo',    3             ),
        ('B',  'bar',    4             )
    )
    SELECT * FROM common_table $$,
    $$
      VALUES
        ('foo'),
        ('bar')
    $$
  ) AS (
    name TEXT,
    foo  INT,
    bar  INT
  );

结果

 name | foo | bar
------+-----+-----
 A    |   1 |   2
 B    |   3 |   4
© www.soinside.com 2019 - 2024. All rights reserved.