MySQL 使用 WHERE 或 JOIN 清理 HAVING

MySQL clean up HAVING with WHERE or JOIN

我有一个查询,当它有 NO 状态为 2 或 3 并且超过 7 天的尝试时获取所有文档:

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)

我将 A.status 分组为状态并检查 2 和 3,然后检查最大日期以查看它是否已存在 7 天。

但是,我听说使用 HAVING 并不是执行此操作的最佳方式,而且我的 LIKE 是一个非常糟糕的主意。有谁知道这是不是真的,或者是否有更好的方法来优化这段代码?我已经用了几天了,这似乎是最快的方法(尝试过子查询和其他一些方法)。

编辑:为了更好地解释结构,文档可以包含无限次尝试。尝试使用 documentId 连接到文档的 ID。

下面的查询比原来的查询效率更高。 LIKE 是一个非常低效的操作,因为它遍历每个字符寻找 2 或 3;寻找完全匹配的效率要高得多,即使这确实需要子查询。

HAVING 子句中编写剩余条件的另一种方法是使用子查询,但这比仅使用 HAVING 效率低,在这种情况下,子查询是一个单独的必须对主查询中的每一行执行的查询。 HAVING 子句只是一个条件,用于检查我们分组所依据的每个值。

这将要求您有 table 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)