我有以下 SQL 语句。它选择特定日期 (
vc
)的访问次数 (
vd
)
SELECT count(vid) vc, date(visitwhen) vd
FROM book_visit
where date(visitwhen) >=date_sub(now(), interval 14 day)
group by vd
order by vd desc
这选择了一系列数据,输出如下所示:
{
"data": [
{
"vc": 2,
"vd": "2023-04-25"
},
{
"vc": 1,
"vd": "2023-04-24"
},
{
"vc": 84,
"vd": "2023-04-23"
},
{
"vc": 17,
"vd": "2023-04-21"
},
{
"vc": 26,
"vd": "2023-04-20"
},
{
"vc": 1,
"vd": "2023-04-19"
},
{
"vc": 3,
"vd": "2023-04-17"
},
{
"vc": 18,
"vd": "2023-04-16"
},
....
我想看到的是:
vc
中的vd
比前一个或下一个vc
/vd
大/小,我也想返回一个+
(或-
)或任何指示一个vc
增加/减少。我可能可以在客户端执行此操作,但我想看看是否可以在 MySQL 中执行此操作。
尝试这样的事情,如果你的 MySQL 支持:
SELECT * FROM (
SELECT dt, num, IF(@oldnum IS NOT NULL, IF(@oldnum > num, '-', '+'), NULL) AS 'change', @oldnum := num
FROM test_data
ORDER BY dt
) t
ORDER BY dt DESC
对于一些测试数据,这将导致类似这样的结果:
dt num change @oldnum := num
---------- ------ ------ ----------------
2023-04-10 15 - 15
2023-04-09 32 + 32
2023-04-08 14 + 14
2023-04-07 13 - 13
2023-04-06 83 + 83
2023-04-05 35 - 35
2023-04-04 63 - 63
2023-04-03 93 + 93
2023-04-02 34 - 34
2023-04-01 59 (NULL) 59
按日期排序 - 将
@oldnum = num
放在末尾,这样对于第一条记录,它将为 NULL。从第 2 条记录开始,它将具有前一条记录的值。 IF
应该在@oldnum = num
之前完成。 IF
将决定 num
中的当前记录与之前记录的 num
相比有何变化,可作为 oldnum
.
是的,或者如@user1191247 所建议的那样,对于 MySQL 8+:https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html
SELECT dt, num, LAG(num) OVER w AS 'prev_num',
IF(LAG(num) OVER w IS NOT NULL, IF(num > LAG(num) OVER w, '+', IF(num < LAG(num) OVER w, '-', '=')), NULL) AS 'change'
FROM test_data
WINDOW w AS (ORDER BY dt)
ORDER BY dt DESC;
dt num prev_num change
---------- ------ -------- --------
2023-04-10 15 32 -
2023-04-09 32 14 +
2023-04-08 14 13 +
2023-04-07 13 83 -
2023-04-06 83 35 +
2023-04-05 35 63 -
2023-04-04 63 93 -
2023-04-03 93 34 +
2023-04-02 34 59 -
2023-04-01 59 (NULL) (NULL)
您当前的日期标准是 non-sargable,因为服务器必须将
DATE()
函数应用于列值才能进行比较:
WHERE DATE(visitwhen) >= DATE_SUB(NOW(), INTERVAL 14 DAY)
应该改为:
WHERE visitwhen >= CURRENT_DATE - INTERVAL 13 DAY
并确保您在
visitwhen
上有一个索引。
您可以使用 LAG() 窗口函数 获取给定表达式的前一行的值:
SELECT COUNT(vid) vc, DATE(visitwhen) vd,
CASE
WHEN COUNT(vid) > LAG(COUNT(vid)) OVER w THEN '+'
WHEN COUNT(vid) < LAG(COUNT(vid)) OVER w THEN '-'
WHEN COUNT(vid) = LAG(COUNT(vid)) OVER w THEN 'nc'
END AS `change`
FROM book_visit
WHERE visitwhen >= CURRENT_DATE - INTERVAL 13 DAY
GROUP BY vd
WINDOW w AS (ORDER BY DATE(visitwhen))
ORDER BY vd DESC;
输出:
VC | vd | 改变 |
---|---|---|
28 | 2023-04-26 | + |
22 | 2023-04-25 | - |
24 | 2023-04-24 | - |
29 | 2023-04-23 | + |
21 | 2023-04-22 | - |
25 | 2023-04-21 | - |
29 | 2023-04-20 | + |
24 | 2023-04-19 | + |
22 | 2023-04-18 | - |
26 | 2023-04-17 | NC |
26 | 2023-04-16 | + |
21 | 2023-04-15 | - |
23 | 2023-04-14 | NC |
23 | 2023-04-13 | 空 |