SELECT DATE_FORMAT(b.checktime,"%Y-%m-%d") AS dtDate,
case when (
SELECT DATE_FORMAT(a.checktime,'%H:%i:%s')
FROM checkinout a
WHERE a.checktype='0'
and a.userid=1
and DATE_FORMAT(a.checktime,'%Y-%m-%d')=DATE_FORMAT(b.checktime,'%Y-%m-%d')
LIMIT 1)
is not NULL
then
(
SELECT
DATE_FORMAT(a.checktime,'%H:%i:%s')
FROM checkinout a
WHERE a.checktype='0'
and a.userid=1
and DATE_FORMAT(a.checktime,'%Y-%m-%d')=DATE_FORMAT(b.checktime,'%Y-%m-%d')
LIMIT 1
)
else 'N/A' END
AS Chkin
from checkinout b
where
DATE_FORMAT(b.checktime,"%m")='06' AND
DATE_FORMAT(b.checktime,"%Y")='2019' AND
DATE_FORMAT(b.checktime,"%w")!='0' AND .
DATE_FORMAT(b.checktime,"%w")!='6' AND .
DATE_FORMAT(b.checktime,"%Y-%m-%d") not in
(select date_s from wend)
GROUP BY dtDate
ORDER BY dtDate DESC
受影响的行:0找到的行:9警告:0 1个查询的持续时间:25.665秒。
此查询出了什么问题,因为9行需要25.665秒
谢谢
答案 0 :(得分:0)
在不了解查询目的的情况下,可以将其重写为:
SELECT DISTINCT date(b.checktime) AS dtDate,
coalesce((
SELECT time(a.checktime)
FROM checkinout a
WHERE a.checktype = '0'
and a.userid = 1
and date(a.checktime) = date(b.checktime)
LIMIT 1
), 'N/A') AS Chkin
from checkinout b
where month(b.checktime) = 6
AND year(b.checktime) = 2019
AND weekday(b.checktime) not in (5, 6) -- non weekend
AND date(b.checktime) not in (select date_s from wend)
ORDER BY dtDate DESC
尽管GROUP BY
的性能可能优于DISTINCT
-您应该同时测试两者。但是,可以优化上述查询以使用索引。
外部条件month(b.checktime) = 6 AND year(b.checktime) = 2019
可以重写为b.checktime >= '2019-06-01' AND b.checktime < '2019-06-01' + INTERVAL 1 MONTH
。这样,引擎就应该能够在(checktime)
上使用索引。
条件date(a.checktime) = date(b.checktime)
可以写为a.checktime >= date(b.checktime) and a.checktime < date(b.checktime) + INTERVAL 1 DAY
。在这里,我建议使用以下索引之一:(checktype, userid, checktime)
,(userid, checktype, checktime)
或(userid, checktime)
。
对于date(b.checktime) not in (select date_s from wend)
,最好使用“反连接”。
这是我要尝试的最终查询:
SELECT DISTINCT date(b.checktime) AS dtDate,
coalesce((
SELECT time(a.checktime)
FROM checkinout a
WHERE a.checktype = '0'
and a.userid = 1
and a.checktime >= date(b.checktime)
and a.checktime < date(b.checktime) + INTERVAL 1 DAY
LIMIT 1
), 'N/A') AS Chkin
from checkinout b
LEFT JOIN wend w ON w.date_s = date(b.checktime)
where b.checktime >= '2019-06-01'
AND b.checktime < '2019-06-01' + INTERVAL 1 MONTH
AND weekday(b.checktime) not in (5, 6) -- non weekend
AND w.date_s IS NULL
ORDER BY dtDate DESC