snowflake-cloud-data-platformpivot-table

How can I perform an Oracle 2-dimensional for-clause pivot in Snowflake?


This pivot output section works fine in Oracle PL/SQL. It does not work in T-SQL.

I now need it to work in Snowflake SQL.

SELECT 
        *
    FROM
    (
    SELECT
                RACE, MNH_G, FNH_G, UNH_G, MH_G, FH_G, UH_G, MU_G, FU_G, UU_G, (TNH_G + THL_G + TU_G + TOTAL_G) AS TOTAL
    FROM
        (
            SELECT
                *
            FROM
                total_demographics

    PIVOT
        (
            COUNT(line_number) as G
            FOR (GENDER, ETHNICITY) IN (
                ('Male','Non-Hispanic') AS MNH,
                ('Female','Non-Hispanic') AS FNH,
                ('Unknown','Non-Hispanic') AS UNH,
                ('Male','Hispanic or Latino') AS MH,
                ('Female','Hispanic or Latino') AS FH,
                ('Unknown','Hispanic or Latino') AS UH,
                ('Male','Unknown') AS MU,
                ('Female','Unknown') AS FU,
                ('Unknown','Unknown') AS UU,
                ('Total','Non-Hispanic') AS TNH,
                ('Total','Hispanic or Latino') AS THL,
                ('Total','Unknown') AS TU,
                ('Total','Total') AS Total
                )       
        )

    ORDER BY (
        case RACE
            when 'American Indian or Alaska Native' then 0
            when 'Asian' then 1
            when 'Native Hawaiian or other Pacific Islander' then 2
            when 'Black' then 3
            when 'White' then 4
            when 'More than one race' then 5
            when 'Unknown' then 6
            when 'Total' then 7
            else
                6
        end
                )
                )
    )

The output of the Oracle query is as follows:

RACE MNH_G FNH_G UNH_G MH_G FH_G UH_G MU_G FU_G UU_G TOTAL
American Indian or Alaska Native 10 9 1 1 2 0 1 3 0 27
Asian 90 80 1 0 2 0 2 3 0 178
Native Hawaiian or other Pacific Islander 2 1 0 0 0 0 0 1 0 4
White 3703 3279 10 103 95 0 128 126 0 7475
More than one race 6 6 0 1 0 0 1 0 0 14
Unknown 412 6265 1 50 40 0 121 401 3 7443
Total 4272 9667 13 159 149 0 294 588 3 15233

The Snowflake compiler doesn't like the "as G" column assignment in the first part of the pivot or the two part (GENDER, ETHNITICY) as well as the multiple values and column assignments in the FOR clause. It's okay with the ORDER BY clause.

How can I get the equivalent of the Oracle 2-dimensional FOR clause in Snowflake SQL (or for that matter T-SQL)?


Solution

  • You can combine multiple columns to array and then pivot:

    -- sample data
    CREATE OR REPLACE TABLE total_demographics AS
    SELECT 'American Indian or Alaska Native' AS Race, 1 AS Line_Number,
           'Male' AS Gender, 'Non-Hispanic' AS ETHNICITY;
    
    -- main query
    SELECT pvt.*
    FROM (SELECT RACE, LINE_NUMBER, [GENDER, ETHNICITY] AS GE
         FROM total_demographics) AS s
    PIVOT(COUNT(LINE_NUMBER) FOR GE IN 
       (['Male','Non-Hispanic'],
        ['Female','Non-Hispanic'],
        ['Unknown','Non-Hispanic']
            -- ...
    )) AS pvt(RACE, MNH, FNH, UMH);
    

    Output:

    +----------------------------------+-----+-----+-----+
    |               RACE               | MNH | FNH | UMH |
    +----------------------------------+-----+-----+-----+
    | American Indian or Alaska Native |   1 |   0 |   0 |
    +----------------------------------+-----+-----+-----+