Відповідь до вчорашньої задачки. Основні проблеми виловив sassa_nf:
SELECT some_date, COUNT(DISTINCT x) as num_x, COUNT(DISTINCT z)
FROM t3
WHERE some_date > some_start_date AND some_date < some_end_date
AND x IN (
SELECT x
FROM t1
WHERE SUBSTRING(y, 1, 11) = 'some_string'
AND LOWERCASE(x) LIKE '%some_other_string%'
AND LOWERCASE(x) NOT LIKE '%yet_another_string%'
)
GROUP BY some_date
ORDER BY num_x
LIMIT 10
UPDATE: Якщо кому не віриться, ось варіант з JOIN'ом, трохи симетричніший на вигляд, а виконується за той самий час або трохи довше, залежно від платформи:
SELECT some_date, COUNT(DISTINCT x) as num_x, COUNT(DISTINCT z)
FROM
(SELECT x
FROM t1
WHERE SUBSTRING(y, 1, 11) = 'some_string'
AND LOWERCASE(x) LIKE '%some_other_string%'
AND LOWERCASE(x) NOT LIKE '%yet_another_string%')
INNER JOIN
(SELECT x,z,some_date
FROM t3
WHERE some_date > some_start_date AND some_date < some_end_date)
USING(x)
GROUP BY 1 ORDER BY 2 LIMIT 10
Але верхній варіант швидший... імхо
SELECT some_date, COUNT(DISTINCT x) as num_x, COUNT(DISTINCT z)
FROM t3
WHERE some_date > some_start_date AND some_date < some_end_date
AND x IN (
SELECT x
FROM t1
WHERE SUBSTRING(y, 1, 11) = 'some_string'
AND LOWERCASE(x) LIKE '%some_other_string%'
AND LOWERCASE(x) NOT LIKE '%yet_another_string%'
)
GROUP BY some_date
ORDER BY num_x
LIMIT 10
UPDATE: Якщо кому не віриться, ось варіант з JOIN'ом, трохи симетричніший на вигляд, а виконується за той самий час або трохи довше, залежно від платформи:
SELECT some_date, COUNT(DISTINCT x) as num_x, COUNT(DISTINCT z)
FROM
(SELECT x
FROM t1
WHERE SUBSTRING(y, 1, 11) = 'some_string'
AND LOWERCASE(x) LIKE '%some_other_string%'
AND LOWERCASE(x) NOT LIKE '%yet_another_string%')
INNER JOIN
(SELECT x,z,some_date
FROM t3
WHERE some_date > some_start_date AND some_date < some_end_date)
USING(x)
GROUP BY 1 ORDER BY 2 LIMIT 10
Але верхній варіант швидший... імхо
no subject
Date: 2021-03-20 10:27 pm (UTC)no subject
Date: 2021-03-20 10:40 pm (UTC)WHERE .... IN ... переважно імплементується через створення хеш таблиці, тоді як JOIN або через неї, або через цикли, як де, тому часом оданково, а часом перше швидше. Ще там можуть різниці виникати за рахунок того, коли саме цю таблицю генерують.
no subject
Date: 2021-03-21 10:26 am (UTC)no subject
Date: 2021-03-21 12:36 am (UTC)no subject
Date: 2021-03-21 01:32 am (UTC)no subject
Date: 2021-03-21 03:19 am (UTC)Да я как-то не верю, что это эквивалентно.
no subject
Date: 2021-03-21 04:15 am (UTC)Я у свій час оптимізував readability, у мене було:
SELECT ...
FROM (SELECT x FROM t1 WHERE [t1 filters]) a
INNER JOIN
(SELECT x,z,some_date FROM t3 WHERE [t3 filters]) b
ON a.x=b.x
GROUP BY ... ORDER ... LIMIT ...
Але варіант з "WHERE x IN ()" замість JOIN'а виглядає швидшим, хоч і не настільки симетричним :)
no subject
Date: 2021-03-21 08:20 am (UTC)В оригіналі маємо count(distinct cte.x). Цей вираз означає, що cte поводиться як set of x і власне порядок і повтори рядків у cte не мають значення. Додаткові умови в group by та sort стосуються лише даних з t3 - повністю визначаються t3. Також, умови в where змушують cte left join t3 поводитись, як inner join (наприклад, lowercase(t3.x) like '....' не може бути задоволене для рядків left join, де t3.x is null).
Тому маємо право викинути сортування і left join з t2 у виразі, який утворює cte (left join не створює нові і не викидає рядки, які існують в t1), і cte left join t3 on cte.x=t3.x на where x in (select ...).
no subject
Date: 2021-03-21 04:03 pm (UTC)Цю задачку для інтерв'ю такі і писали: взяли нормальний СЕЛЕКТ і пододавали зайвого :)