плохо знаком со снежинкой - проблема с оператором SQL с объединениями и поворотными значениями - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь смоделировать продукт, имея таблицу с ссылками на характеристики c таблица с таблицей 3 ко многим

например,

  • Product (productId, brand, описание, модель)
  • ProductCharacteristi c (идентификатор продукта, характеристика ID)
  • характеристика c (идентификатор характеристики, тип, имя, значение)

Из этой структуры Я пытаюсь повернуть обратно в один результат, чтобы отобразить поля продукта с и характеристику c .type характеристику c .value в операторе выбора.

Например:

select distinct 
    p.ProductId, p.name, p.description, p.brand, p.model, body, DoorNum
from    
    Product p
left join   
    ProductionCharacteristic pc on p.ProductId = pc.ProductId,
    (select CharacteristicId, "'Body'" as body, "'DoorNum'" as DoorNum  
     from Characteristic c
     pivot (max(c.name) for c.type IN ('Body' , 'DoorNum')))  temp
where  
    pc.CharacteristicId = temp.CharacteristicId

Проблема 1: является ли any_Value агрегатной функцией? это не нравится pivot, я использую max () вместо Issue2: вышеупомянутый выбор возвращает 3 строки. есть ли способ свести это к одной записи?

1 Ответ

0 голосов
/ 11 февраля 2020

Примечания

  1. Я должен настаивать на том, чтобы вы НИКОГДА не использовали смешанные выражения соединения. Это означает, что если вы собираетесь использовать ключевые слова JOIN и LEFT JOIN , не используйте , и наоборот.
  2. Вы не дали понять, что вы ожидал, что ваш вывод будет выглядеть, поэтому я собираюсь использовать список, разделенный запятыми, но также покажу, как вы можете использовать массив.
  3. Я вставил это как комментарий, но стоит повторить: ANY_VALUE () агрегатная функция, но не работает в контексте PIVOT https://community.snowflake.com/s/question/0D50Z00008uVHTYSA4/anyvalue-does-not-work-on-pivot

Параметры запроса

Опция 1 - Встроенный свод (не рекомендуется, так как его сложнее читать, и подзапрос сводки нельзя использовать повторно)

select 
    p.ProductId
    , p.name
    , p.description
    , p.brand
    , p.model
    , listagg(temp.body,', ') as body
    , listagg(temp.DoorNum,', ') as doornum1
    , arrayagg(temp.DoorNum) as doornum2
from    
    Product p
left join
    ProductionCharacteristic pc 
        on p.ProductId = pc.ProductId
join (
      select CharacteristicId, body, doornum
      from Characteristic c
      pivot (max(c.name) for c.type IN ('Body' , 'DoorNum')) as p (CharacteristicId, value, body, doornum)
    )  temp
    on pc.CharacteristicId = temp.CharacteristicId
group by 1,2,3,4,5
;

Вариант 2 - сводка в CTE (рекомендуется)

with temp as (
  select CharacteristicId, body, doornum
  from Characteristic c
  pivot (max(c.name) for c.type IN ('Body' , 'DoorNum')) as p (CharacteristicId, value, body, doornum)
)
select 
    p.ProductId
    , p.name
    , p.description
    , p.brand
    , p.model
    , listagg(temp.body,', ') as body
    , listagg(temp.DoorNum,', ') as doornum1
    , arrayagg(temp.DoorNum) as doornum2
from    
    Product p
left join
    ProductionCharacteristic pc 
        on p.ProductId = pc.ProductId
join temp
    on pc.CharacteristicId = temp.CharacteristicId
group by 1,2,3,4,5
;

Вариант 3 - боковое соединение (Как коррелированный подзапрос)

select 
    p.ProductId
    , p.name
    , p.description
    , p.brand
    , p.model
    , temp.body
    , temp.doornum1
    , temp.doornum2
from    
    Product p
join lateral (
    select listagg(iff(type = 'Body',name,null),', ') as body
        ,listagg(iff(type = 'DoorNum',name,null),', ') as doornum1
        ,arrayagg(iff(type = 'DoorNum',name,null)) as doornum2
    from Characteristic c
    join ProductionCharacteristic pc 
            on pc.CharacteristicId = c.CharacteristicId
    where p.ProductId = pc.ProductId
    ) temp
;

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...