我正在尝试使用 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
在某种不同的上下文中运行。我该如何让它发挥作用?
您需要做的就是将字符串内的
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