mysql - MySQL中SELECT查询中的值分配和使用IF-ELSE
问题描述
示例表
| TIME | NAME | VALUE
-----------------------+-------+---------------------
2020-11-19 11:10:13 | A | 12.3
2020-11-19 11:10:13 | B | 14.1
2020-11-19 11:10:13 | C | 10.3
2020-11-19 11:11:34 | B | 21.3
2020-11-19 11:12:45 | A | 32.1
2020-11-19 11:12:45 | C | 40.3
2020-11-19 11:13:05 | A | 13.1
当 A、B、C 的值改变时,保存。
所以示例表“2020-11-19 11:11:34”只保存 B,因为 A 和 C 在“2020-11-19 11:10:13”上没有改变
我想按时间选择 A、B、C 值组
示例结果在这里
| TIME | A | B | C |
-----------------------+-------+-------+-----------
2020-11-19 11:10:13 | 12.3 | 14.1 | 10.3
2020-11-19 11:11:34 | 12.3 | 21.3 | 10.3
2020-11-19 11:12:45 | 32.1 | 21.3 | 40.3
2020-11-19 11:13:05 | 13.1 | 21.3 | 40.3
第一步,“按时间和名称获取价值”已完成
第一个结果是这样的。
| TIME | A | B | C |
-----------------------+-------+-------+-----------
2020-11-19 11:10:13 | 12.3 | 14.1 | 10.3
2020-11-19 11:11:34 |(NULL) | 21.3 | (NULL)
2020-11-19 11:12:45 | 32.1 |(NULL) | 40.3
2020-11-19 11:13:05 | 31.1 |(NULL) | (NULL)
它只有在那个时候才有价值。
所以我创建了一个存储过程来获取搜索时间之前的最新值。
CREATE PROCEDURE `GetValuesByTime`(
IN `StartDate` DATETIME,
IN `EndDate` DATETIME
)
BEGIN
DECLARE lastA DOUBLE;
DECLARE lastB DOUBLE;
DECLARE lastC DOUBLE;
SET @lastA = 0;
SET @lastB = 0;
SET @lastC = 0;
SELECT VALUE
INTO lastA
FROM data_log
WHERE TIME <= StartDate order by TIME desc LIMIT 1;
SELECT VALUE
INTO lastB
FROM data_log
WHERE TIME <= StartDate order by TIME desc LIMIT 1;
SELECT VALUE
INTO lastC
FROM data_log
WHERE TIME <= StartDate order by TIME desc LIMIT 1;
SELECT
TIME,
IFNULL(sum(NAME) = 'A' THEN VALUE END), lastA) AS 'A',
IFNULL(sum(NAME) = 'B' THEN VALUE END), lastB) AS 'B',
IFNULL(sum(NAME) = 'C' THEN VALUE END), lastC) AS 'C',
FROM data_log
WHERE TIME >= StartDate AND TIME <= EndDate
group BY TIME;
END
但它还有问题...当 VALUE 不为空时,不会更新 lastA、lastB、lastC
该程序结果在这里
| TIME | A | B | C |
-----------------------+-------+-------+-----------
2020-11-19 11:10:13 | 12.3 | 14.1 | 10.3
2020-11-19 11:11:34 | 12.3 | 21.3 | 10.3
2020-11-19 11:12:45 | 32.1 | 14.1 | 40.3
2020-11-19 11:13:05 | 31.1 | 14.1 | 10.3
'2020-11-19 11:13:05' C 不是 10.3,而是 40.3,因为有一个更新的值。
但它没有改变。
在这个部分,
SELECT
TIME,
IFNULL(sum(NAME) = 'A' THEN VALUE END), lastA) AS 'A',
IFNULL(sum(NAME) = 'B' THEN VALUE END), lastB) AS 'B',
IFNULL(sum(NAME) = 'C' THEN VALUE END), lastC) AS 'C',
FROM data_log
WHERE TIME >= StartDate AND TIME <= EndDate
group BY TIME;
我可以像这样使用 IF-ELSE 吗?
SELECT
TIME,
IF (sum(NAME) = 'A' THEN VALUE END) = null THEN lastA
ELSE VALUE, lastA := VALUE AS 'A',
IF (sum(NAME) = 'B' THEN VALUE END) = null THEN lastB
ELSE VALUE, lastB := VALUE
IF (sum(NAME) = 'C' THEN VALUE END) = null THEN lastC
ELSE VALUE, lastC := VALUE
FROM data_log
WHERE TIME >= StartDate AND TIME <= EndDate
group BY TIME;
有可能吗?
如何获得我想要的结果?
编辑)我使用 MariaDB 10.5
解决方案
这是 2 个单独的任务,而不是一个任务:
- 查找每个名称和每次的实际值。它有简单的解决方案:
WITH
cte1 AS ( SELECT DISTINCT name FROM data_log ),
cte2 AS ( SELECT DISTINCT `time` FROM data_log )
SELECT DISTINCT
cte1.name,
cte2.`time`,
FIRST_VALUE(data_log.value) OVER (PARTITION BY cte1.name, cte2.`time` ORDER BY data_log.`time` DESC) value
FROM cte1
CROSS JOIN cte2
LEFT JOIN data_log ON data_log.name = cte1.name
AND data_log.`time` <= cte2.`time`
ORDER BY name, `time`
- 透视数据。列
name
列表是静态的,因此我们可以对上一个任务的结果使用条件聚合:
WITH
cte1 AS ( SELECT DISTINCT name FROM data_log ),
cte2 AS ( SELECT DISTINCT `time` FROM data_log ),
cte3 AS ( SELECT DISTINCT
cte1.name,
cte2.`time`,
FIRST_VALUE(data_log.value) OVER (PARTITION BY cte1.name, cte2.`time` ORDER BY data_log.`time` DESC) value
FROM cte1
CROSS JOIN cte2
LEFT JOIN data_log ON data_log.name = cte1.name
AND data_log.`time` <= cte2.`time` )
SELECT `time`,
MAX(CASE WHEN name = 'A' THEN value END) A,
MAX(CASE WHEN name = 'B' THEN value END) B,
MAX(CASE WHEN name = 'C' THEN value END) C
FROM cte3
GROUP BY `time`
推荐阅读
- windows - php表单将数据插入数据库
- javascript - Javascript函数没有被HTML文件解析
- python - Pillow - 尝试在图像上写入文本时出现 KeyError
- augmented-reality - 如何在定制的 Snapdragon Board 上运行 ARcore?
- reactjs - React-router-dom 链接更改 url 但不更新视图
- javascript - 如何验证用户的产品是否已经存在?
- docker - pod init 中 argo 图像的图像拉回退
- java - 添加两个矩阵的索引越界错误
- laravel - 每页样式表
- javascript - 如何修复导航器/窗口/文档在 Nuxt 中未定义