Одним из решений является добавление GROUP BY
.Во-первых, вы должны понять, почему.
У вас есть запрос агрегации без GROUP BY
.Это всегда собирается произвести одну строку.Однако неагрегированный столбец (domain
) будет иметь значение , произвольное .В вашем сравнении он может совпадать или не совпадать с доменом.
Это можно исправить несколькими способами.Наиболее эффективным является отказ от domain
в SELECT
и просто ссылка на него в WHERE
:
SELECT COUNT(*)
FROM links l
WHERE source = 'web' AND
last_seen >= CURDATE() AND -- probably no last_seen values in the future
'testingwebsite.com' = SUBSTRING_INDEX( TRIM( LEADING 'www.' FROM TRIM( LEADING 'http://' FROM TRIM( LEADING 'https://' FROM link ) ) ), '/', 1 )
Это гарантированно вернет одну строку, независимо от того, соответствуют ли строкиWHERE
пункт.Если ни одна строка не совпадает, то счет будет 0
Я подозреваю, что это то, что вы хотите.
Обратите внимание, что я также изменил сравнение дат.Это позволяет запросу использовать индекс для links(source, last_seen)
.
Наконец, если вы действительно хотите домен в SELECT
, но не хотите повторять его, я рекомендую подзапрос:
SELECT domain, COUNT(*)
FROM (SELECT l.*,
SUBSTRING_INDEX( TRIM( LEADING 'www.' FROM TRIM( LEADING 'http://' FROM TRIM( LEADING 'https://' FROM link ) ) ), '/', 1 ) as domain
FROM links l
) l
WHERE source = 'web' AND
last_seen >= CURDATE() AND -- probably no last_seen values in the future
domain = 'testingwebsite.com'
GROUP BY domain;
Обратите внимание, что это не будет возвращать строк, если домен не существует в данных.
Комментарий к производительности.Эта версия материализует подзапрос, который несет накладные расходы (и является недостатком MySQL, но не других баз данных).Однако ваша версия не только материализует подзапрос, но и объединяет все данные, поэтому это все равно должно быть быстрее, чем при использовании HAVING
.В общем случае лучше фильтровать до агрегации , чем после.