I'm trying to use perform a pivot operation on some data using Postgres' tablefunc
extension's CROSSTAB
function. The data needs to undergo some transformations first, which I perform in some common table expressions.
However, it appears CROSSTAB
can't see the results of those expressions.
For example, this query sourcing data from a temporary table works fine:
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
);
and, as expected, produces the following output:
name | foo | bar
text | integer | integer
---- | ------- | -------
A | 1 | 2
B | 3 | 4
But the same query, this time using common table expressions doesn't run:
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
)
and produces the following error:
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
I take it this means the text query (SELECT * FROM common_table
) runs in some sort of different context?
Note: The tablefunc
extension must be enabled for CROSSTAB
to be available:
CREATE EXTENSION IF NOT EXISTS tablefunc;
All you need to do is move your CTE
inside the string as the first argument to crosstab(text, text)
function just like you did with the select statement. It will be parsed and executed properly. This is because you provide full SQL statement that produces the source set in first argument.
You need to double your quotation marks inside the string or use dollar-quoting $$
just like you did with the second argument and I did below:
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
);
Result
name | foo | bar
------+-----+-----
A | 1 | 2
B | 3 | 4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With