#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 . . . Эту структуру также довольно легко изменить-и, вероятно, ее можно было бы сделать еще проще, если цель состоит в том, чтобы передать значения один раз.