创建具有多个类别的 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;