为什么这个 CASE GREATEST 返回 NULL?
Why is this CASE GREATEST returning NULL?
我有一个看起来像这样的 select 查询,这样我就知道哪个日期是最新的 (dtStart) 以及哪个 table 最新的日期来自 (TableOrigin)。
WITH ranked_entity AS (
SELECT
table5.id,
GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')) as dtStart,
CASE GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')
)
WHEN table1.dtEvaluationStart THEN 'table1'
WHEN table2.dtStart THEN 'table2'
WHEN table3.dtEvaluationStart THEN 'table3'
WHEN table4.dtStart THEN 'table4'
END AS TableOrigin,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY dtStart DESC) AS rn
FROM table5
LEFT JOIN table1 ON table5.id = table1.fid
LEFT JOIN table2 ON table5.id = table2.fid
LEFT JOIN table3 ON table5.id = table3.fid
LEFT JOIN table4 ON table5.id = table4.fid
)
SELECT * FROM ranked_entity WHERE rn = 1;
但有时 TableOrigin 为 NULL,即使设置了 dtStart。为什么会这样?
例如,在一行中,dtStart 列的值“2020-05-14 14:34:18”取自 table3,因为它是列中的最新日期四个 table。这意味着列 TableOrigin 应该具有该行的值 'table3'。但是 TableOrigin 是 NULL。
并非所有行都发生这种情况,在某些行中,TableOrigin 值是正确的。
示例数据:
table5
+-----+
| id |
+-----+
| 198 |
| 197 |
+-----+
table1
+-----+---------------------+
| fid | dtEvaluationStart |
+-----+---------------------+
| 198 | 2018-01-11 13:59:17 |
| 197 | 2020-01-21 09:29:35 |
+-----+---------------------+
table2
+-----+---------------------+
| fid | dtStart |
+-----+---------------------+
| 198 | 2018-02-01 12:57:50 |
| 197 | 2020-11-18 10:14:31 |
+-----+---------------------+
table3
+-----+---------------------+
| fid | dtStart |
+-----+---------------------+
| 197 | 2018-01-10 14:58:19 |
+-----+---------------------+
table4
+-----+---------------------+
| fid | dtStart |
+-----+---------------------+
| 198 | 2020-03-01 09:40:09 |
| 197 | 2020-03-04 08:10:59 |
+-----+---------------------+
output
+-----+---------------------+-------------+
| id | dtStart | TableOrigin |
+-----+---------------------+-------------+
| 198 | 2020-03-01 09:40:09 | NULL |
| 197 | 2020-11-18 10:14:31 | table2 |
+-----+---------------------+-------------+
dstart
总是会被设置。但是,如果值为'0000-00-00 00:00:00'
,那么所有比较的值(大概)都是NULL
。常数值不匹配 NULL
因此列名不匹配。
NULL
值表达了这一点。
如果在这种情况下您还希望 dtstart
成为 NULL
,则使用 NULLIF()
:
NULLIF(GREATEST(COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')
), '0000-00-00 00:00:00'
)
尽管代码在 MySql 中运行良好,但在 MariaDB 中不起作用。
作为解决方法,您可以在 CASE
表达式中重复 COALESCE()
:
WITH ranked_entity AS (
SELECT
table5.id,
GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')) as dtStart,
CASE GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')
)
WHEN COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00') THEN 'table1'
WHEN COALESCE(table2.dtStart, '0000-00-00 00:00:00') THEN 'table2'
WHEN COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00') THEN 'table3'
WHEN COALESCE(table4.dtStart, '0000-00-00 00:00:00') THEN 'table4'
END AS TableOrigin,
ROW_NUMBER() OVER (PARTITION BY table5.id ORDER BY table4.dtStart DESC) AS rn
FROM table5
LEFT JOIN table1 ON table5.id = table1.fid
LEFT JOIN table2 ON table5.id = table2.fid
LEFT JOIN table3 ON table5.id = table3.fid
LEFT JOIN table4 ON table5.id = table4.fid
)
SELECT * FROM ranked_entity WHERE rn = 1;
参见demo。
结果:
> id | dtStart | TableOrigin | rn
> --: | :------------------ | :---------- | -:
> 197 | 2020-11-18 10:14:31 | table2 | 1
> 198 | 2020-03-01 09:40:09 | table4 | 1
我有一个看起来像这样的 select 查询,这样我就知道哪个日期是最新的 (dtStart) 以及哪个 table 最新的日期来自 (TableOrigin)。
WITH ranked_entity AS (
SELECT
table5.id,
GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')) as dtStart,
CASE GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')
)
WHEN table1.dtEvaluationStart THEN 'table1'
WHEN table2.dtStart THEN 'table2'
WHEN table3.dtEvaluationStart THEN 'table3'
WHEN table4.dtStart THEN 'table4'
END AS TableOrigin,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY dtStart DESC) AS rn
FROM table5
LEFT JOIN table1 ON table5.id = table1.fid
LEFT JOIN table2 ON table5.id = table2.fid
LEFT JOIN table3 ON table5.id = table3.fid
LEFT JOIN table4 ON table5.id = table4.fid
)
SELECT * FROM ranked_entity WHERE rn = 1;
但有时 TableOrigin 为 NULL,即使设置了 dtStart。为什么会这样?
例如,在一行中,dtStart 列的值“2020-05-14 14:34:18”取自 table3,因为它是列中的最新日期四个 table。这意味着列 TableOrigin 应该具有该行的值 'table3'。但是 TableOrigin 是 NULL。 并非所有行都发生这种情况,在某些行中,TableOrigin 值是正确的。
示例数据:
table5
+-----+
| id |
+-----+
| 198 |
| 197 |
+-----+
table1
+-----+---------------------+
| fid | dtEvaluationStart |
+-----+---------------------+
| 198 | 2018-01-11 13:59:17 |
| 197 | 2020-01-21 09:29:35 |
+-----+---------------------+
table2
+-----+---------------------+
| fid | dtStart |
+-----+---------------------+
| 198 | 2018-02-01 12:57:50 |
| 197 | 2020-11-18 10:14:31 |
+-----+---------------------+
table3
+-----+---------------------+
| fid | dtStart |
+-----+---------------------+
| 197 | 2018-01-10 14:58:19 |
+-----+---------------------+
table4
+-----+---------------------+
| fid | dtStart |
+-----+---------------------+
| 198 | 2020-03-01 09:40:09 |
| 197 | 2020-03-04 08:10:59 |
+-----+---------------------+
output
+-----+---------------------+-------------+
| id | dtStart | TableOrigin |
+-----+---------------------+-------------+
| 198 | 2020-03-01 09:40:09 | NULL |
| 197 | 2020-11-18 10:14:31 | table2 |
+-----+---------------------+-------------+
dstart
总是会被设置。但是,如果值为'0000-00-00 00:00:00'
,那么所有比较的值(大概)都是NULL
。常数值不匹配 NULL
因此列名不匹配。
NULL
值表达了这一点。
如果在这种情况下您还希望 dtstart
成为 NULL
,则使用 NULLIF()
:
NULLIF(GREATEST(COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')
), '0000-00-00 00:00:00'
)
尽管代码在 MySql 中运行良好,但在 MariaDB 中不起作用。
作为解决方法,您可以在 CASE
表达式中重复 COALESCE()
:
WITH ranked_entity AS (
SELECT
table5.id,
GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')) as dtStart,
CASE GREATEST(
COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table2.dtStart, '0000-00-00 00:00:00'),
COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00'),
COALESCE(table4.dtStart, '0000-00-00 00:00:00')
)
WHEN COALESCE(table1.dtEvaluationStart, '0000-00-00 00:00:00') THEN 'table1'
WHEN COALESCE(table2.dtStart, '0000-00-00 00:00:00') THEN 'table2'
WHEN COALESCE(table3.dtEvaluationStart, '0000-00-00 00:00:00') THEN 'table3'
WHEN COALESCE(table4.dtStart, '0000-00-00 00:00:00') THEN 'table4'
END AS TableOrigin,
ROW_NUMBER() OVER (PARTITION BY table5.id ORDER BY table4.dtStart DESC) AS rn
FROM table5
LEFT JOIN table1 ON table5.id = table1.fid
LEFT JOIN table2 ON table5.id = table2.fid
LEFT JOIN table3 ON table5.id = table3.fid
LEFT JOIN table4 ON table5.id = table4.fid
)
SELECT * FROM ranked_entity WHERE rn = 1;
参见demo。
结果:
> id | dtStart | TableOrigin | rn
> --: | :------------------ | :---------- | -:
> 197 | 2020-11-18 10:14:31 | table2 | 1
> 198 | 2020-03-01 09:40:09 | table4 | 1