Объединение похожих запросов Athena (Presto) - PullRequest
0 голосов
/ 14 октября 2019

Я новичок в SQL и других языках запросов, поэтому у меня есть некоторые сомнения по поводу них.

У меня есть два следующих запроса в Афине, которые очень похожи, но в одном случае дополнительным параметром являетсяпрошло, и ВНУТРЕННЕЕ СОЕДИНЕНИЕ используется. Первый получает количество различных значений в одном столбце определенной таблицы, а второй делает то же самое, но объединяет две таблицы и добавляет ограничение для другого столбца, используя объединенные таблицы.

--Query #1
SELECT COUNT(DISTINCT(usertoken)) users
FROM "database"

WHERE country = ${country}
and serverdate between CAST('${fromdate}' As DATE) and CAST('${todate}' As DATE) 


--Query #2
SELECT COUNT(DISTINCT(usertoken)) users
FROM "database" op
INNER JOIN "location_0" cities
ON op.loc0id = cities.id

WHERE openings.country = ${country}
and openings.serverdate between CAST('${fromdate}' As DATE) and CAST('${todate}' As DATE)
and cities.id in (${cities_list})

Где параметры между $ {} передаются извне и имеют строковый тип, кроме $ {towns_list}, который представляет собой список целых чисел (даты приводятся к DATE). Оба работают нормально и без проблем.

Мой вопрос следующий : Могу ли я использовать только один запрос для выполнения обеих операций, в зависимости от значения towns_list ? Перед выполнением этих запросов я проверяю, является ли это значение Нулевым или нет, и в зависимости от этого я выполняю один или другой, но я бы хотел, чтобы только один запрос мог выполнить оба случая (так как большинствоони одинаковы, и я не хочу иметь избыточный код).

TL; DR: я хочу объединить эти два запроса в один, который работает правильно для обоих случаев ( towns_list имеет значение или равно Null ), добавляя последнее условие, только если определенный параметр не равен Null (и, если возможно, делает только INNER JOIN, если параметр не равен Null ).

Спасибо!

Ответы [ 2 ]

2 голосов
/ 14 октября 2019

Вы можете сделать условное агрегирование:

SELECT 
    COUNT(DISTINCT usertoken) users1,
    COUNT(DISTINCT CASE WHEN ci.id in (${ci.list}) THEN usertoken END) users2
FROM "database" op
INNER JOIN "location_0" cities ci ON op.loc0id = ci.id
WHERE 
    op.country = ${country}
    AND op.serverdate between CAST('${fromdate}' As DATE) and CAST('${todate}' As DATE)
1 голос
/ 14 октября 2019

Вы можете использовать JOIN и COUNT(DISTINCT), но вам нужно LEFT JOIN:

SELECT COUNT(DISTINCT op.usertoken) as users,
       COUNT(DISTINCT CASE WHEN cities.id in (${cities_list}) THEN op.usertoken END) as users_2
FROM "database" op LEFT JOIN
     "location_0" cities
     ON op.loc0id = cities.id
WHERE openings.country = ${country} AND
      openings.serverdate between CAST('${fromdate}' As DATE) and CAST('${todate}' As DATE);

Тем не менее, вполне возможно, что JOIN вообще не нужен, еслион используется только для поиска одного значения:

SELECT COUNT(DISTINCT op.usertoken) as users,
       COUNT(DISTINCT CASE WHEN op.loc0id in (${cities_list}) THEN op.usertoken END) as users_2
FROM "database" op 
WHERE openings.country = ${country} AND
      openings.serverdate between CAST('${fromdate}' As DATE) and CAST('${todate}' As DATE);
...