malyj_gorgan: (Default)
[personal profile] malyj_gorgan
Відповідь до вчорашньої задачки. Основні проблеми виловив 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


Але верхній варіант швидший... імхо

Date: 2021-03-20 10:27 pm (UTC)
From: [personal profile] ichthuss
Хм, а where x in (select ...) працює швидше, ніж inner join? Інтуїтивно мені здавалось, що ймовірніше навпаки.

Date: 2021-03-21 10:26 am (UTC)
From: [personal profile] sassa_nf
я не знаю, як БД влаштовані насправді, але з точки зору можливої реалізації - where x in (select ...) дає змогу обрубувати деякі обчислення в (select ...) - з контексту зрозуміло, що достатньо знайти один рядок, який задовольняє x in ... (неповний index scan), тоді як inner join вимагає щось робити із повторами (full table scan).

Date: 2021-03-21 12:36 am (UTC)
ppk_ptichkin: (Default)
From: [personal profile] ppk_ptichkin
Ха, я ещё подумал, что там join лишние, наверное - но что я знаю..

Date: 2021-03-21 03:19 am (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Да я как-то не верю, что это эквивалентно.

Date: 2021-03-21 08:20 am (UTC)
From: [personal profile] sassa_nf
я підходив до спрощення так: (правда, піддивившись, що інші кажуть, бо сам прогавив)

В оригіналі маємо 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 ...).

Profile

malyj_gorgan: (Default)
malyj_gorgan

January 2026

S M T W T F S
     1 23
45 6 7 8910
11121314151617
18192021222324
25262728293031

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 11th, 2026 10:05 pm
Powered by Dreamwidth Studios