Поиск минимальных значений с помощью нескольких объединений

#sql #google-bigquery #left-join #minimum

#sql #google-bigquery #левое соединение #минимальный

Вопрос:

Я использую StandardSQL в BigQuery и имею 7 таблиц по 10-75 столбцов в каждой и тысячи строк. Для простоты я буду использовать только соответствующие таблицы и столбцы для того, что я пытаюсь выполнить.

Таблица 1

Элемент Desc
12341 abcd
23451 bcda
34561 cdab
45671 dabc

Таблица 2

Подпункт Расположение ON_OFF Из первых рук OnOrder
12345 1 НА 3 5
12345 2 НА 4 2
12345 3 НА 2 4
12346 1 НА 7 7
12346 2 НА 1 4
12346 3 НА 8 7
23451 1 ВЫКЛ 1 1
23451 2 ВЫКЛ 3 2
34567 1 НА 6 0
34567 2 НА 1 5
34568 1 НА 2 0
34568 2 НА 3 10
45671 2 НА 5 1

Таблица 3

Элемент Подпункт
12341 12346
23451 23451
34561 34567
34561 34568

Текущий результат

Элемент Desc ON_OFF О OO
12341 abcd НА 9 11
12341 abcd НА 16 18
23451 bcda ВЫКЛ 4 3
34561 cdab НА 7 5
34561 cdab НА 5 10
45671 dabc НА 5 1

Желаемый результат

Элемент Desc ON_OFF О OO
12341 abcd НА 9 18
23451 bcda ВЫКЛ 4 3
34561 cdab НА 5 5
45671 dabc НА 5 1

Я ищу минимальное значение OH и минимальное значение OO для каждого элемента, и, как и в случае с элементом 45671, это не соответствует одному и тому же номеру подпункта.

Текущий код, предоставляющий мне текущую таблицу результатов, является:

 Select 
Table1.Item,
Table1.Desc,
Table2.ON_OFF,
Table2.OH,
Table2.OO
From Table1
Left Join Table3
On Table1.Item = Table3.Item
Left Join 
    (Select SubItem, ON_OFF, Sum(OnHand) As OH, Sum(OnOrder) As OO
        From Table 2
        Group by 1,2)
ON Table3.SubItem = Table2.SubItem;
 

Ищу идеи, поскольку я все еще новичок в SQL, и текущий фактический код связывает 7 таблиц с различными объединениями, чтобы построить итоговую таблицу с 45 столбцами и тысячами строк. Я рассмотрел использование RowNumber() и Partition By , но я не уверен, куда это приведет. Также думал, что разделение OO и OH на два объединения может помочь.

Любые предложения приветствуются! Спасибо!

Комментарии:

1. Ваша постановка задачи и результаты не совпадают. «18» не является минимальным значением OO для первого элемента.

Ответ №1:

Глядя на ваши примеры данных, кажется, что вы можете использовать group by и агрегировать функцию min следующим образом:

 Select Table1.Item,
       Table1.Desc,
       Table2.ON_OFF,
       Min(Table2.OH),
       Min(Table2.OO)
  From Table1
  Left Join Table3
    On Table1.Item = Table3.Item
  Left Join (Select SubItem,
                    ON_OFF, 
                    Sum(OnHand) As OH,
                    Sum(OnOrder) As OO
               From Table2
              Group by 1,2) Table2
    ON Table3.SubItem = Table2.SubItem
Group by Table1.Item, Table1.Desc, Table2.ON_OFF;
 

Ответ №2:

Я работал с ним после того, как получил столь необходимый сон…

Я придумал следующее, и оно работает!

 SELECT T1.Item, 
 T1.Desc,
 T3_1.ONOFF, 
 T3_1.OH,
 T3_2.OO
 FROM Table1 T1

 Left Join
    (Select Item, SubItem,T2_1.O_O as ONOFF, T2_1.OH1 as OH,
    ROW_NUMBER() OVER(PARTITION BY Item ORDER BY T2_1.OH1) as rn
    FROM T2_1
    Left Join
      (Select SubItem, SUM(IFNULL(OnHand,0)) AS OH1,
      FROM  Table2 
      GROUP BY 1) T2_1
    ON T2_1.SubItem = T3_1.SubItem) T3_1
  On T1.Item = T3_1.Item
  
 Left Join
    (Select Item, SubItem, T2_2.OO1 as OO,
    ROW_NUMBER() OVER(PARTITION BY Item ORDER BY T2_2.OO1) as rn2
    FROM T2_2
    Left Join
      (Select SubItem, SUM(IFNULL(OnOrder,0)) AS OO1,
      FROM  Table2 
      GROUP BY 1) T2_2
    ON T2_2.SubItem = T3_2.SubItem) T3_2
  On T1.Item = T3_2.Item
 
 Where rn = 1 and rn2 = 1;
 

Спасибо!

Комментарии:

1. если вы действительно думаете, что ваш ответ действительно работает — пожалуйста, дважды проверьте его — у вас могут быть некоторые опечатки — пожалуйста, исправьте это!