3
votes

So I can't figure out how to get tables to pivot in Snowflake. I'm trying to model the help page here https://docs.snowflake.com/en/sql-reference/constructs/pivot.html.

In this example, I'm only pulling 3 columns, the step, the parameter being measured and the value. Trying to pivot it so each parameter is in its own column.

source output

step_name    Parameter_Name Value
----------------------------------
A            Item1          75
A            Item2          32
B            Item1          45
B            Item2          62

pivot output

step_name    Item1    Item2
--------------------------
 A            75       32
 B            45       62

sql text:

select 
    step_name, 
    PARAMETER_NAME,
    Value

from "METRO_TABLE" 
pivot (avg(Value) for PARAMETER_NAME in ('Item1', 'Item2'))
as p

WHERE 
and PARAMETER_NAME in ('Item1','Item2')

limit 50 
3
I wrote a Snowflake stored procedure to get dynamics pivots inside Snowflake, check hoffa.medium.com/…Felipe Hoffa

3 Answers

4
votes

Just use conditional aggregation. The syntax works across most databases, and does not require remembering the slight variations of each vendor-specific implementation. It is also more flexible (although this does not make a difference for this simple use-case):

select
    step_name,
    max(case when parameter_name = 'Item1' then value end) Item1,
    max(case when parameter_name = 'Item2' then value end) Item2
from metro_table
where parameter_name in ('Item1', 'Item2')
group by step_name

In absence of an order by clause, I removed the limit clause from your query: if you want a stable subsets of rows, then use both order by and limit.

2
votes

Using Snowflake syntax, the following SQL gives the output.

 Select *
  FROM METRO_TABLE
  PIVOT(sum(value) for parameter_name in ('Item1','Item2'))
  AS P (Step_Name,Item_1,Item_2)
  ORDER BY step_name;
0
votes

I had a similar issue. I had to use a CTE to get it to work properly.

WITH metro_tbl AS (

  select 
      step_name, 
      parameter_name,
      value
  from metro_table
  where parameter_name in ('Item1','Item2')
  limit 50 
)
 
  select * 
  from metro_tbl
  pivot(avg(value) for parameter_name in ('Item1', 'Item2'))