2015-04-19 3 views
0

У меня есть запрос, который получает все документы, когда он имеет Удары с NO статус 2 или 3, которые старше, чем за 7 дней:MySQL очистить HAVING с WHERE или JOIN

SELECT D.*, 
GROUP_CONCAT(A.status) as statuses, 
MAX(A.datetime) as maxDate FROM documents D 

LEFT JOIN attempts A on A.documentId = D.id 

GROUP BY D.id 

HAVING statuses NOT LIKE '%2%' 
AND statuses NOT LIKE '%3%' 
AND DATE(maxDate) < DATE_SUB(CURDATE(), INTERVAL 7 DAY) 

Я группируя А. статус в статусы и проверку на 2 и 3, а затем проверку даты MAX, чтобы узнать, не прошло ли 7 дней.

Но, я слышал, что использование HAVING - не лучший способ сделать это, и что мой LIKE - очень плохая идея. Кто-нибудь знает, верно ли это или есть лучший способ оптимизировать этот код? Я занимаюсь этим уже несколько дней, и это, по-видимому, самый быстрый метод (попробованные подзапросы и несколько других методов).

EDIT: Чтобы объяснить структуру немного лучше, документ может содержать неограниченное количество попыток. Попытки подключиться к идентификатору документа с помощью documentId.

+0

Я думаю, проблема может быть решена путем изменения того, как вы присоединяетесь к таблицам. Не могли бы вы дать некоторую информацию о структуре таблицы попыток? – Devon

+0

Только уточнить: Нет статуса 2,3 И старше 7 дней = статус 2,3 разрешен, если документу всего 6 дней? –

+0

Должны быть выполнены все три условия: никогда не может быть 2 или 3, а дата всегда должна быть старше 7 дней. –

ответ

0

Следующий запрос более эффективен, чем оригинал. LIKE - очень неэффективная операция, потому что она проходит через каждого персонажа, ищущего 2 или 3; гораздо эффективнее искать точное совпадение, даже если для этого требуется подзапрос.

Альтернативный способ записи оставшегося условия в предложении HAVING заключается в использовании подзапроса, но это будет более неэффективно, чем просто использование HAVING в этом случае, поскольку подзапрос представляет собой отдельный запрос, который должен быть выполнен для каждой строки в основном запросе. Предложение HAVING - это просто условие, которое проверяется для каждого значения, которое мы группируем.

Для этого вам потребуется первичный ключ для таблицы attempts; Я назвал его attempt_id.

SELECT D.*, 
MAX(A.datetime) as maxDate 
FROM documents D 
LEFT JOIN attempts A on A.documentId = D.id 
WHERE NOT EXISTS (SELECT status 
        FROM attempts A2 
        WHERE A2.attempt_id = A.attempt_id 
        AND A2.status = 2 
         OR A2.status = 3) 
GROUP BY D.id 
HAVING DATE(maxDate) < DATE_SUB(CURDATE(), INTERVAL 7 DAY) 
Смежные вопросы