SQL работает в Athena Engine v1, но не в v2

#sql #amazon-athena

Вопрос:

У меня есть SQL-запрос, встроенный в систему, которая до сих пор успешно работала в Athena с движком версии 1. Однако в версии 2 движка это не удается, и я не смог понять, почему.

Вот обобщенная версия SQL. Он суммирует количество людей в 3 группах: взрослые, жители Нью-Йорка и их совпадение. (Взрослые Нью-Йорка).

В версии 1 это работает, но в версии 2 я получаю ошибку «столбец z.id_field не может быть разрешен».

 WITH BASE AS (SELECT person_id, age, state
              FROM people 
              WHERE gender  = 'male'
                 )

    ,group_a as (
SELECT distinct (person_id) as id_field
FROM BASE
WHERE age > 17
),
  
  group_b as (
SELECT distinct (person_id) as id_field
FROM BASE
WHERE state = 'NY'
)


SELECT CASE WHEN z.id_field is null then 'group_b_only' WHEN r.id_field is null then 'group_a_only' ELSE 'Overlap' END as group
      , COUNT (coalesce (z.id_field, r.id_field)) as count
FROM group_a AS z FULL OUTER JOIN group_b as r USING (id_field)
GROUP BY 1;
 

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

1. Я не знаю Афину, но в некоторых базах данных, которые я видел, ИСПОЛЬЗУЕТСЯ (id_field) для свертывания z.id_field и r.id_field в один столбец id_field, не привязанный ни к z, ни к r. Попробуйте просто id_field без префикса z.

2. @Rup . . . Оба должны поддерживаться using .

3. @GordonLinoff Я бы тоже так подумал, но я только что нашел его снова. Это был столбец Oracle 19c, ORA-25154, часть предложения USING не может иметь квалификатора.

4. @Rup . . . Это действительно, действительно странно. Как вы должны проверить, есть ли совпадение во внешнем join ? [Я не жду, что ты ответишь на этот вопрос.]

Ответ №1:

В качестве примечания, в любой базе данных это было бы проще в виде агрегирования и, вероятно, также быстрее:

 SELECT grp, COUNT(*)
FROM (SELECT person_id,
             (CASE WHEN MAX(age) > 17 AND MAX(state) = 'NY' THEN 'Both'
                   WHEN MAX(age) > 17 THEN 'Age Only'
                   ELSE 'State Only'
              END) as grp
      FROM people 
      WHERE gender  = 'male' AND
            (age > 17 OR state = 'NY')
      GROUP BY person_id
     ) x
GROUP BY grp;
 

Вышесказанное предполагает, что person_id это может быть повторено в people . Если это не так, то это можно упростить до:

 SELECT (CASE WHEN age > 17 AND state = 'NY' THEN 'Both'
             WHEN age > 17 THEN 'Age Only'
             ELSE 'State Only'
         END) as grp, COUNT(*)
FROM people 
WHERE gender  = 'male' AND
      (age > 17 OR state = 'NY')
GROUP BY grp;
     
 

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

1. Спасибо Гордону, он был структурирован таким образом, чтобы код c# мог легко редактировать SQL для изменения определений group_a и group_b. SQL, который я опубликовал, значительно упрощен, чтобы продемонстрировать сообщение об ошибке Athena.

2. @Bill0688 . . . Эту структуру также довольно легко изменить-и, вероятно, ее можно было бы сделать еще проще, если цель состоит в том, чтобы передать значения один раз.