0

I am new to snowflake and I have a scenario with table having below data,

Combined1 Combined2 Common_code
Name       John      ABC123
City       NY        ABC123
Sex        M         ABC123
Country    USA       ABC123
Name       John      ABC123
City       BF        ABC123
Sex        M         ABC123
Country    USA       ABC123
Name       Lucy      XYZ456
City       CB        XYZ456
Sex        F         XYZ456
Country    UK        XYZ456

So that I want to transpose the table so that the result would look like

Name City Sex Country Common_code
John NY   M   USA     ABC123
John BF   M   USA     ABC123
Lucy CB   F   UK      XYZ456

I have tried multiple approaches using PIVOT, FLATTEN but couldn't crack this up. Main condition is I don't want to lose any record as per the above example. Any response or solution is highly appreciated in Snowflake.

2
  • Hi - please format your data as tables so it is readable. Also update your question with the SQL you’ve managed to write so far Commented Dec 9, 2023 at 17:47
  • Why have you asked for “no aggregation” and “any solution” Commented Dec 9, 2023 at 18:21

1 Answer 1

0

so using a CTE for the data:

with data(Combined1, Combined2, Common_code) as (
    select *
    from values
        ('Name', 'John', 'ABC123'),
        ('City', 'NY', 'ABC123'),
        ('Sex', 'M', 'ABC123'),
        ('Country', 'USA', 'ABC123'),
        ('Name', 'John', 'ABC123'),
        ('City', 'BF', 'ABC123'),
        ('Sex', 'M', 'ABC123'),
        ('Country', 'USA', 'ABC123'),
        ('Name', 'Lucy', 'XYZ456'),
        ('City', 'CB', 'XYZ456'),
        ('Sex', 'F', 'XYZ456'),
        ('Country', 'UK', 'XYZ456')
)

so here is the most likely "optimal" aggregation version that you want to avoid, albeit it, you have duplicate values in your common_code, so this data appears suspect.

select
    max(iff(Combined1='Name',Combined2,null)) as Name
    ,max(iff(Combined1='City',Combined2,null)) as City
    ,max(iff(Combined1='Sex',Combined2,null)) as Sex
    ,max(iff(Combined1='Country',Combined2,null)) as Country
    ,Common_code
from data
group by Common_code
order by Common_code;

But the above relies on the "common code" being distinct per thing of interest. Which it is not, thus the two rows.

enter image description here

Which means we can just do it the classic worst way possible, and let the DB build all combinations, and then throw most the work away, way:

select distinct 
    name.combined2 as name
    ,city.combined2 as City
    ,sex.combined2 as Sex
    ,country.combined2 as Country
    ,name.common_code
from data as name
join data as city
    on name.common_code = city.common_code
        and city.combined1 = 'City'
join data as sex
    on name.common_code = sex.common_code
        and sex.combined1 = 'Sex'
join data as country
    on name.common_code = country.common_code
        and country.combined1 = 'Country'
where name.combined1 = 'Name'
order by name.common_code;

which gives:

enter image description here

this could be framed in sub-selects (or CTE's) and make NATURAL JOIN do some work also like so:

select distinct
    *
from (
    select combined2 as name, common_code 
    from data 
    where combined1 = 'Name'
) as a
natural join 
(
    select combined2 as city, common_code 
    from data 
    where combined1 = 'City'
) as b
natural join 
(
    select combined2 as sex, common_code 
    from data 
    where combined1 = 'Sex'
) as c  
natural join 
(
    select combined2 as country, common_code 
    from data 
    where combined1 = 'Country'
) as d
;

but now the column order is less under our control (only because I allowed the join order to define it).

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.