简体   繁体   English

当三个值之一为 NULL 时,如何避免在 CASE 中返回 NULL

[英]How to avoid returning a NULL in CASE when one of the three values is NULL

I want to thank you in advance for your help on this matter.我想提前感谢你在这件事上的帮助。

I'm writing a SQL query in Oracle SQL Developer which needs to compare 3 dates and return the earliest one, avoiding blank values and writing that value somewhere along the lines.我正在 Oracle SQL Developer 中编写一个 SQL 查询,它需要比较 3 个日期并返回最早的日期,避免空白值并将该值写入某处。

My question is what do you think is the best way to avoid those NULL values, my take is below but I'm having some slight issues implementing this in my current setup.我的问题是您认为避免这些 NULL 值的最佳方法是什么,我的看法如下,但我在当前设置中遇到了一些小问题。

Cheers!干杯!

SELECT Case When DATE1 < DATE2 And DATE1 < DATE3 Then DATE1
            When DATE2 < DATE1 And DATE2 < DATE3 Then DATE2
            Else DATE3
            End AS xxx, SOME.TABLE|| ' ' || TABLE.SOME INTO TABLE1, TABLE2
            
FROM (SELECT Case When DATE1 IS NULL Then DATEADD(year, 100, GETDATE()) Else DATE1 As DATE1,
             Case When DATE2 IS NULL Then DATEADD(year, 100, GETDATE()) Else DATE2 As DATE2,
             Case When DATE3 IS NULL Then DATEADD(year, 100, GETDATE())
             Else DATE3 As DATE3
        FROM SOME_TABLE2 ST2 WHERE SOME_TABLE3 = '#INTO_SOMETHING')

You can use LEAST and COALESCE :您可以使用LEASTCOALESCE

SELECT LEAST(
         COALESCE(date1, date2, date3, ADD_MONTHS(SYSDATE, 100*12)),
         COALESCE(date2, date3, date1, ADD_MONTHS(SYSDATE, 100*12)),
         COALESCE(date3, date1, date2, ADD_MONTHS(SYSDATE, 100*12))
       ) AS least_date
FROM   table_name;

or:要么:

SELECT COALESCE(
         LEAST(
           COALESCE(date1, date2, date3),
           COALESCE(date2, date3, date1),
           COALESCE(date3, date1, date2)
         ),
         ADD_MONTHS(SYSDATE, 100*12)
       ) AS least_date
FROM   table_name;

or:要么:

SELECT LEAST(
         COALESCE(date1, ADD_MONTHS(SYSDATE, 100*12)),
         COALESCE(date2, ADD_MONTHS(SYSDATE, 100*12)),
         COALESCE(date3, ADD_MONTHS(SYSDATE, 100*12))
       ) AS least_date
FROM   table_name;

Note: the first two queries will return the least non- NULL value from your table in preference to the default value 100 years from now.注意:前两个查询将从您的表中返回最少的非NULL值,而不是 100 年后的默认值。 The final query may return the default value 100 years from now if all the other values are a mix of NULL and non- NULL values that are greater than 100 years from now.如果所有其他值都是NULL和非NULL值的混合,这些值从现在起超过 100 年,则最终查询可能会返回 100 年后的默认值。 Which you use depends on the logic you want to implement and whether your table will ever contain dates more than 100 years in the future.您使用哪个取决于您要实现的逻辑以及您的表是否会包含未来 100 多年的日期。

Which, for the sample data:其中,对于示例数据:

CREATE TABLE table_name (date1, date2, date3) AS
SELECT DATE '2022-01-01', DATE '2021-01-01', DATE '2020-01-01' FROM DUAL UNION ALL
SELECT DATE '2022-01-01', NULL, DATE '2020-01-01' FROM DUAL UNION ALL
SELECT DATE '2022-01-01', DATE '2021-01-01', NULL FROM DUAL UNION ALL
SELECT NULL, DATE '2021-01-01', NULL FROM DUAL UNION ALL
SELECT NULL, NULL, NULL FROM DUAL;

All output:所有output:

LEAST_DATE至少_DATE
2020-01-01 00:00:00 2020-01-01 00:00:00
2020-01-01 00:00:00 2020-01-01 00:00:00
2021-01-01 00:00:00 2021-01-01 00:00:00
2021-01-01 00:00:00 2021-01-01 00:00:00
2122-12-05 09:50:28 2122-12-05 09:50:28

fiddle小提琴


If you do want a NULL value if, and only if, all 3 dates are NULL then use the first query without the default date:如果当且仅当所有 3 个日期都是NULL时您确实需要NULL值,然后使用没有默认日期的第一个查询:

SELECT LEAST(
         COALESCE(date1, date2, date3),
         COALESCE(date2, date3, date1),
         COALESCE(date3, date1, date2)
       ) AS least_date
FROM   table_name;

fiddle小提琴

Here is a little paralel results Using LEAST() function alone, with Nvl() and CASE with Nvl.这是单独使用 LEAST() function、Nvl() 和 CASE 与 Nvl 的一些并行结果。 The Last one will return Null if all 3 date columns are Null.如果所有 3 个日期列都是 Null,最后一个将返回 Null。
Sample data:样本数据:

WITH
    tbl As 
        (
            Select 1 "NMBR", 'A' "LTTR", SYSDATE "DATE1", SYSDATE-1 "DATE2", SYSDATE+1 "DATE3" From Dual Union All
            Select 2 "NMBR", 'B' "LTTR", SYSDATE "DATE1", SYSDATE-1 "DATE2", Null "DATE3" From Dual Union All
            Select 3 "NMBR", 'C' "LTTR", SYSDATE "DATE1", Null "DATE2", SYSDATE+1 "DATE3" From Dual Union All
            Select 4 "NMBR", 'D' "LTTR", Null "DATE1", SYSDATE-1 "DATE2", SYSDATE+1 "DATE3" From Dual Union All
            Select 5 "NMBR", 'E' "LTTR", Null "DATE1", Null "DATE2", SYSDATE+1 "DATE3" From Dual Union All
            Select 6 "NMBR", 'F' "LTTR", Null "DATE1", Null "DATE2", NULL "DATE3" From Dual 
        )
NMBR核反应堆 LTTR LTTR DATE1日期 1 DATE2日期2 DATE3日期3
1 1个 A一种 05-DEC-22 22 年 12 月 5 日 04-DEC-22 22 年 12 月 4 日 06-DEC-22 22 年 12 月 6 日
2 2个 B 05-DEC-22 22 年 12 月 5 日 04-DEC-22 22 年 12 月 4 日
3 3个 C C 05-DEC-22 22 年 12 月 5 日 06-DEC-22 22 年 12 月 6 日
4 4个 D 04-DEC-22 22 年 12 月 4 日 06-DEC-22 22 年 12 月 6 日
5 5个 E 06-DEC-22 22 年 12 月 6 日
6 6个 F F

SQL SQL

SELECT 
    NMBR,
    LTTR,
    LEAST(DATE1, DATE2, DATE3) "LEAST_DATE",
    LEAST(Nvl(DATE1, TRUNC(SYSDATE)+10000), Nvl(DATE2, TRUNC(SYSDATE)+10000), Nvl(DATE3, TRUNC(SYSDATE)+10000)) "LEAST_NVL_DATE",
    CASE  
          WHEN LEAST(Nvl(DATE1, TRUNC(SYSDATE)+10000), Nvl(DATE2, TRUNC(SYSDATE)+10000), Nvl(DATE3, TRUNC(SYSDATE)+10000)) < TRUNC(SYSDATE+1000) 
          THEN LEAST(Nvl(DATE1, TRUNC(SYSDATE)+10000), Nvl(DATE2, TRUNC(SYSDATE)+10000), Nvl(DATE3, TRUNC(SYSDATE)+10000))
    END "LEAST_CASE_NVL_DATE"
FROM
  tbl

Result:结果:

NMBR核反应堆 LTTR LTTR LEAST_DATE至少_DATE LEAST_NVL_DATE LEAST_NVL_DATE LEAST_CASE_NVL_DATE LEAST_CASE_NVL_DATE
1 1个 A一种 04-DEC-22 22 年 12 月 4 日 04-DEC-22 22 年 12 月 4 日 04-DEC-22 22 年 12 月 4 日
2 2个 B 04-DEC-22 22 年 12 月 4 日 04-DEC-22 22 年 12 月 4 日
3 3个 C C 05-DEC-22 22 年 12 月 5 日 05-DEC-22 22 年 12 月 5 日
4 4个 D 04-DEC-22 22 年 12 月 4 日 04-DEC-22 22 年 12 月 4 日
5 5个 E 06-DEC-22 22 年 12 月 6 日 06-DEC-22 22 年 12 月 6 日
6 6个 F F 22-APR-50 22-APR-50

I've been able to resolve the issue by using LEAST and COALESCE functions, since DATEADD and GETDATE are not Oracle functions.我已经能够通过使用 LEAST 和 COALESCE 函数解决这个问题,因为 DATEADD 和 GETDATE 不是 Oracle 函数。

Further to this, I've used @MT0 resolution query which worked well in my current setup.除此之外,我还使用了@MT0 分辨率查询,它在我当前的设置中运行良好。

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

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