Ошибка BigQuery при использовании оператора CASE в ON для LEFT JOIN - PullRequest
0 голосов
/ 05 февраля 2020

Мне нужна помощь в понимании этой ошибки, которую я получаю в BigQuery:

LEFT OUTER JOIN нельзя использовать без условия, равного полям с обеих сторон соединения .

Я пытаюсь использовать оператор case, чтобы изменить строки, выбранные для объединения, в зависимости от значения в строке левой таблицы. Я делаю нечто подобное в некоторых других местах, и это работает, поэтому часть меня думает, что я могу ошибаться в отношении псевдонимов таблиц и имен столбцов, но я не могу понять это. Вот минимальный пример того, что я пытаюсь сделать:

WITH t1 AS (
  SELECT "milk" AS dairy,
   1 AS id,
   2 AS other_id

   UNION ALL

   SELECT "yogurt" AS dairy,
   3 AS id,
   4 AS other_id

   UNION ALL

   SELECT "cheese" AS dairy,
   5 AS id,
   6 AS other_id
),

t2 AS (
  SELECT "blue" AS color,
  1 AS id

  UNION ALL

  SELECT "red" AS color,
  4 AS id
)

SELECT
  t1.*, t2
FROM t1
LEFT JOIN t2 ON
  CASE
    WHEN t1.dairy = 'milk' THEN t1.id = t2.id
    WHEN t1.dairy = 'yogurt' THEN t1.other_id = t2.id
  END

Результат, который я хотел бы видеть:

enter image description here

Как вы можете видеть в желаемом результате, когда значение для dairy равно milk, я хочу, чтобы id из t2 равнялся столбцу id в t1, но когда значение для dairy это yogurt, я хочу, чтобы id из t2 равнялся столбцу other_id в t1.

Я искал объяснение, но не могу понять это. Я также попробовал предлагаемое решение здесь , но получил ту же ошибку, поэтому я думаю, что я просто что-то путаю с именами таблиц или псевдонимами.

Пожалуйста, помогите!

ОБНОВЛЕНИЕ

Мне удалось избавиться от ошибки, переписав case case следующим образом:

SELECT
  t1.*, t2
FROM t1
LEFT JOIN t2 ON
  CASE
    WHEN t1.dairy = 'milk' THEN t1.id
    WHEN t1.dairy = 'yogurt' THEN t1.other_id
  END = t2.id

Однако в моей реальной проблеме мне нужно присоединиться к третьему столу аналогичным образом. Если t2.color равно blue, я хочу присоединиться на основе t2.id = t3.id, но если t2.color равно red, я хочу присоединиться на основе t2.id = t3.other_id. Как только я это делаю, возникает та же ошибка. Вот полный пример моей попытки:

WITH t1 AS (
  SELECT "milk" AS dairy,
   1 AS id,
   2 AS other_id

   UNION ALL

   SELECT "yogurt" AS dairy,
   3 AS id,
   4 AS other_id

   UNION ALL

   SELECT "cheese" AS dairy,
   5 AS id,
   6 AS other_id
),

t2 AS (
  SELECT "blue" AS color,
  1 AS id

  UNION ALL

  SELECT "red" AS color,
  4 AS id
),

t3 AS (
  SELECT "sunny" AS weather,
  1 AS id,
  10 AS other_id

  UNION ALL

  SELECT "cloudy" AS weather,
  11 AS id,
  4 AS other_id
)

SELECT
  t1.*, t2, t3
FROM t1
LEFT JOIN t2 ON
  CASE
    WHEN t1.dairy = 'milk' THEN t1.id
    WHEN t1.dairy = 'yogurt' THEN t1.other_id
  END = t2.id
LEFT JOIN t3 ON
  CASE
   WHEN t2.color = 'blue' THEN t3.id
   WHEN t2.color = 'red' THEN t3.other_id
  END = t2.id

Но теперь возникает та же ошибка:

LEFT OUTER JOIN нельзя использовать без условия, равного равенству полей из обе стороны объединения.

Если я удаляю соединение t3, оно работает правильно. Вот еще несколько изображений таблиц и желаемого результата в случае, если это поможет:

enter image description here

Ответы [ 2 ]

1 голос
/ 06 февраля 2020

Мне удалось ответить на ваш обновленный вопрос с 3 таблицами, разбив объединения и соответствующие логики c на отдельные CTE.

WITH t1 AS (
  SELECT "milk" AS dairy, 1 AS id, 2 AS other_id UNION ALL
  SELECT "yogurt", 3, 4 UNION ALL
  SELECT "cheese", 5, 6
),
t2 AS (
  SELECT "blue" AS color, 1 AS id UNION ALL
  SELECT "red", 4
),
t3 AS (
  SELECT "sunny" AS weather, 1 as id, 10 as other_id UNION ALL
  SELECT "cloudy", 11, 4
),
join_t1_t2 as (
  select
    t1.*,
    case 
      when t1.dairy = 'milk' then milk.color
      when t1.dairy = 'yogurt' then yogurt.color
      else null
    end as t2_color,
    case 
      when t1.dairy = 'milk' then milk.id
      when t1.dairy = 'yogurt' then yogurt.id
      else null
    end as t2_id
  from t1
  left join t2 milk on t1.id = milk.id
  left join t2 yogurt on t1.other_id = yogurt.id
),
join_t1_t2_t3 as (
  select
    join_t1_t2.*,
    case 
      when t2_color = 'blue' then blue.id
      when t2_color = 'red' then red.id
      else null
    end as t3_id,
    case 
      when t2_color = 'blue' then blue.other_id
      when t2_color = 'red' then red.other_id
      else null
    end as t3_other_id,
    case 
      when t2_color = 'blue' then blue.weather
      when t2_color = 'red' then red.weather
      else null
    end as t3_weather,
  from join_t1_t2
  left join t3 blue on t2_id = blue.id
  left join t3 red on t2_id = red.other_id
)
select * from join_t1_t2_t3
1 голос
/ 05 февраля 2020

Ниже для BigQuery Standard SQL

#standardSQL
SELECT *,
  ARRAY(
    SELECT AS STRUCT *  
    FROM t2 b
    WHERE b.id IN (a.id, a.other_id) 
    ORDER BY (
      CASE
        WHEN dairy IN ('milk', 'yogurt') THEN 1
        ELSE 2
      END    
    )
    LIMIT 1
  )[SAFE_OFFSET(0)] AS t2  
FROM t1 a  

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

Row dairy   id  other_id    t2.color    t2.id    
1   milk    1   2           blue        1    
2   yogurt  3   4           red         4    
3   cheese  5   6           
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...