简体   繁体   English

为什么这个 CASE GREATEST 返回 NULL?

[英]Why is this CASE GREATEST returning NULL?

I have a select query that looks like this, so that I know which date is the newest (dtStart) and which table the newest date comes from (TableOrigin).我有一个看起来像这样的 select 查询,以便我知道哪个日期是最新的(dtStart)以及最新日期来自哪个表(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;

But sometimes the TableOrigin is NULL even though dtStart is set.但有时即使设置了 dtStart,TableOrigin 也是 NULL。 Why is that so?为什么呢?

For example in one row the column dtStart has the value '2020-05-14 14:34:18' that is taken from table3, because it is the newest date out of the columns of the four tables.例如,在一行中,列 dtStart 具有取自 table3 的值“2020-05-14 14:34:18”,因为它是四个表的列中的最新日期。 That means that the column TableOrigin should have the value 'table3' for this row.这意味着 TableOrigin 列应该具有该行的值“table3”。 But instead TableOrigin is NULL.但是 TableOrigin 是 NULL。 This doesn't happen with all the rows, in some rows the TableOrigin value is correct.并非所有行都发生这种情况,在某些行中 TableOrigin 值是正确的。

Sample Data:样本数据:

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 is always going to be set. dstart总是会被设置。 However, if the value is '0000-00-00 00:00:00' , then all the compared values are (presumably) NULL .但是,如果该值为'0000-00-00 00:00:00' ,则所有比较值都是(大概) NULL The constant value doesn't match NULL so the column name is not matched.常量值与NULL不匹配,因此列名不匹配。

The NULL value is expressing this. NULL值表达了这一点。

If you also want dtstart to be NULL in this case, then use NULLIF() :在这种情况下,如果您还希望dtstartNULL ,则使用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'
      )

Although the code works fine in MySql, it does not work in MariaDB.尽管该代码在 MySql 中运行良好,但在 MariaDB 中无法运行。
As a workaround you can repeat COALESCE() in your CASE expression:作为一种解决方法,您可以在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;

See the demo .请参阅演示
Results:结果:

>  id | dtStart             | TableOrigin | rn
> --: | :------------------ | :---------- | -:
> 197 | 2020-11-18 10:14:31 | table2      |  1
> 198 | 2020-03-01 09:40:09 | table4      |  1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM