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)
我有一个查询,当它有 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)