postgresql 无法在Postgres交叉表查询中使用公共表表达式

yws3nbqq  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(197)

我尝试使用Postgres的tablefunc扩展的CROSSTAB函数对一些数据执行pivot操作。数据需要首先进行一些转换,我在一些 * 公共表表达式 * 中执行。
但是,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
  );

字符串
并如预期的那样产生以下输出:
| 名称|Foo|酒吧|
| --|--|--|
| 一| 1 | 2 |
| B| 3 | 4 |
但是同样的查询,这次使用了 common table expressions,并没有运行:

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在某种不同的上下文中运行。我如何使它工作?

oaxa6hgo

oaxa6hgo1#

你所需要做的就是将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

相关问题