SELECT 中的值分配和使用 IF-ELSE 在 MySQL 中查询
Value Assign and Use IF-ELSE in SELECT Query in MySQL
示例table
| 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的值改变时,保存。
所以例子table,'2020-11-19 11:11:34'只保存B,因为A和C在'2020-11-19 11:10:13'
我想得到 select 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
第一步,'Get Value By Time and Name'完成
第一个结果是这样的
| 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`
示例table
| 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的值改变时,保存。
所以例子table,'2020-11-19 11:11:34'只保存B,因为A和C在'2020-11-19 11:10:13'
我想得到 select 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
第一步,'Get Value By Time and Name'完成
第一个结果是这样的
| 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`