BigQuery / SQL: Как объединить две таблицы и использовать значение столбца в качестве имени столбца? - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть эти таблицы:

Продукты

| food_id | title    |
| 1       | soy milk |
| 2       | banana   |
| 3       | apple    |

Питательные вещества

| food_id | nutrient_id | amount |
| 1       | n1          | 0.05   |
| 1       | n2          | 2      |
| 1       | n3          | 34     |
...

Мне нужно это:

| food_id | title    | n1   | n2 | n3 |
| 1       | soy milk | 0.05 | 2  | 34 |
| 2       | banana   |      |    |    |  
| 3       | apple    |      |    |    |

Struct также будет работать.

Я знаю все объединения, но не могу обдумать это ... как мне вставить nutrient_id в заголовок столбца или Struct ключ?

Ответы [ 4 ]

2 голосов
/ 20 апреля 2020

Ниже для стандарта BigQuery SQL и предполагает, что количество питательных веществ не фиксировано для каждой еды, поэтому поворотный подход не будет простым и скорее отвечает на следующий вопрос:

как мне поставить nutritionent_id в ... ключ структуры?

#standardSQL
SELECT *
FROM `project.dataset.Foods` 
LEFT JOIN (
  SELECT food_id, ARRAY_AGG(STRUCT(nutrient_id, amount)) nutrients_facts
  FROM `project.dataset.Nutrients`
  GROUP BY food_id
)
USING(food_id)  

Если применить приведенное выше к выборочным данным из вашего вопроса - результат будет

enter image description here

2 голосов
/ 20 апреля 2020

Использование ROW_NUMBER с поворотной логикой c:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY food_id ORDER BY nutrient_id) rn
    FROM Nutrients
)

SELECT
    f.food_id,
    f.title,
    MAX(CASE WHEN t.rn = 1 THEN t.amount END) AS n1,
    MAX(CASE WHEN t.rn = 2 THEN t.amount END) AS n2,
    MAX(CASE WHEN t.rn = 3 THEN t.amount END) AS n3
FROM Foods f
LEFT JOIN cte
    ON f.food_id = t.food_id
GROUP BY
    f.food_id,
    f.title;
2 голосов
/ 20 апреля 2020

Если у вас есть фиксированный список питательных веществ, то вы можете использовать join и group by:

select f.food_id, f.title,
       max(case when n.nutrient_id = 1 then n.amount end) as nutrient_1,
       max(case when n.nutrient_id = 2 then n.amount end) as nutrient_2,
       max(case when n.nutrient_id = 3 then n.amount end) as nutrient_3
from foods left join
     nutrients n
     on n.food_id = f.food_id
group by f.food_id, f.title;

Примечание: здесь используется left join, если в ваших данных есть такие продукты, как Twinkies, которые не имеют известной питательной ценности.

Если вы не знаете полный список питательных веществ, то вы не знаете, какие столбцы находятся в наборе результатов. Я бы предложил использовать JSON или массивы для представления значений.

1 голос
/ 20 апреля 2020

Попробуйте это

  Select food_id, title, 

  max( case when nutrient_id =
   'n1' then 
   amount end) as n1, 
   max( case when nutrient_id =
   'n2' then 
   amount end) as n2, 
  max( case when nutrient_id =
   'n3' then 
   amount end) as n3
  from table1 t1 join
   Table2 t2
 on t1.food_id=t2.food_id
 Group by food_id, title
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...