创建具有多个类别的 Postgresql 交叉表查询
Create Postgresql Crosstab Query with multiple categories
到目前为止,我已经创建了一个可以得到以下结果的查询:
+------------+----------+-------------+-------+
| date | category | subcategory | count |
+------------+----------+-------------+-------+
| 2020-04-23 | One | First | 1 |
| 2020-04-23 | Two | Second | 1 |
| 2020-04-23 | Two | First | 3 |
| 2020-04-23 | Three | Third | 3 |
| 2020-04-23 | Three | Second | 1 |
| 2020-04-23 | Four | Second | 2 |
| 2020-04-23 | Five | Third | 3 |
| 2020-04-23 | Five | Second | 1 |
| 2020-04-23 | Five | First | 1 |
| 2020-04-23 | Six | Third | 1 |
| 2020-04-23 | Six | Second | 2 |
+------------+----------+-------------+-------+
我想把它变成下面的但我想不出来:
+------------+----------+-------+--------+-------+
| date | category | First | Second | Third |
+------------+----------+-------+--------+-------+
| 2020-04-23 | One | 1 | 0 | 0 |
| 2020-04-23 | Two | 2 | 3 | 0 |
| 2020-04-23 | Three | 0 | 1 | 3 |
| 2020-04-23 | Five | 1 | 2 | 3 |
| 2020-04-23 | Six | 0 | 2 | 1 |
+------------+----------+-------+--------+-------+
我尝试了以下方法,但是 所以它不起作用:
SELECT *
FROM crosstab(
$$
SELECT date, category, subcategory, count(*)
-- ...
GROUP BY 1, 2, 3
$$
)
AS ct(date date, category text, First int, Second int, Third int);
有没有办法在使用交叉表时为行指示符使用多个值,或者我必须找到其他方法吗?
我找到了一个解决方案,尽管它并不理想:将前两个与唯一字符合并,使用 CTE 获取交叉表查询,然后拆分结果列。它看起来像:
WITH crosstb AS (
SELECT *
FROM crosstab(
$$
-- Concatenate date and category columns
SELECT date || '_' || category, subcategory, count(*)
-- ...
GROUP BY 1, 2
$$,
-- Specify data columns to ensure null-count rows are included
$$VALUES ('First'), ('Second'), ('Third')$$
)
AS ct(datecat text, First numeric, Second numeric, Third numeric)
)
SELECT
-- Split datecat column into separate again
(regexp_split_to_array(datecat, '_'))[1]::date as Date,
(regexp_split_to_array(datecat, '_'))[2] as category,
COALESCE(First, 0),
COALESCE(Second, 0),
COALESCE(Third, 0)
FROM crosstb;
到目前为止,我已经创建了一个可以得到以下结果的查询:
+------------+----------+-------------+-------+
| date | category | subcategory | count |
+------------+----------+-------------+-------+
| 2020-04-23 | One | First | 1 |
| 2020-04-23 | Two | Second | 1 |
| 2020-04-23 | Two | First | 3 |
| 2020-04-23 | Three | Third | 3 |
| 2020-04-23 | Three | Second | 1 |
| 2020-04-23 | Four | Second | 2 |
| 2020-04-23 | Five | Third | 3 |
| 2020-04-23 | Five | Second | 1 |
| 2020-04-23 | Five | First | 1 |
| 2020-04-23 | Six | Third | 1 |
| 2020-04-23 | Six | Second | 2 |
+------------+----------+-------------+-------+
我想把它变成下面的但我想不出来:
+------------+----------+-------+--------+-------+
| date | category | First | Second | Third |
+------------+----------+-------+--------+-------+
| 2020-04-23 | One | 1 | 0 | 0 |
| 2020-04-23 | Two | 2 | 3 | 0 |
| 2020-04-23 | Three | 0 | 1 | 3 |
| 2020-04-23 | Five | 1 | 2 | 3 |
| 2020-04-23 | Six | 0 | 2 | 1 |
+------------+----------+-------+--------+-------+
我尝试了以下方法,但是
SELECT *
FROM crosstab(
$$
SELECT date, category, subcategory, count(*)
-- ...
GROUP BY 1, 2, 3
$$
)
AS ct(date date, category text, First int, Second int, Third int);
有没有办法在使用交叉表时为行指示符使用多个值,或者我必须找到其他方法吗?
我找到了一个解决方案,尽管它并不理想:将前两个与唯一字符合并,使用 CTE 获取交叉表查询,然后拆分结果列。它看起来像:
WITH crosstb AS (
SELECT *
FROM crosstab(
$$
-- Concatenate date and category columns
SELECT date || '_' || category, subcategory, count(*)
-- ...
GROUP BY 1, 2
$$,
-- Specify data columns to ensure null-count rows are included
$$VALUES ('First'), ('Second'), ('Third')$$
)
AS ct(datecat text, First numeric, Second numeric, Third numeric)
)
SELECT
-- Split datecat column into separate again
(regexp_split_to_array(datecat, '_'))[1]::date as Date,
(regexp_split_to_array(datecat, '_'))[2] as category,
COALESCE(First, 0),
COALESCE(Second, 0),
COALESCE(Third, 0)
FROM crosstb;