Oracle SQL - 将 CASE 表达式从月份更改为特定日期(BETWEEN)[已关闭]

问题描述 投票:0回答:2

我正在尝试转换查看月份的现有 CASE 表达式,而不是让它查看确切的日期。

CASE
    WHEN reg_con * tagg_reading <60 and to_char(read_date,'mm') in ('06','07','08','09') then 'Y'
    WHEN reg_con * tagg_reading <90 and to_char(read_date,'mm') in ('01','02','03','04','05','10','11','12') then 'Y'
ELSE 'N'
END as Keep_Flag

我的更改已运行,但结果不正确

CASE
   WHEN reg_con * tagg_reading <60 and to_char(read_date, 'MM-DD') BETWEEN '6-15' AND '10-15' then 'Y'
   WHEN reg_con * tagg_reading <90 and to_char(read_date, 'MM-DD') BETWEEN '10-16' AND '6-14' then 'Y'
ELSE 'N'
END as Keep_Flag

感谢任何调整帮助。

CASE 表达式的结果用于过滤 WHERE 语句中的数据

WHERE keep_flag = 'Y'
sql oracle-sqldeveloper
2个回答
1
投票

您的第二种情况表达式有两个直接问题。

首先,默认情况下日期元素是用零填充的,因此如果

read_date
是 2024-06-15,则转换
to_char(read_date, 'MM-DD')
将给出“06-15”,而不是“6-15”。

其次,值的顺序对于

BETWEEN
很重要,如文档中所述

如果 expr3 < expr2, then the interval is empty.

因此,当与字符串进行比较时,“6-15”和“10-15”之间不会有任何日期值,因为“1”按字母顺序排在“6”之前 - 并且没有任何内容匹配

BETWEEN '6' AND '1'
,因为“1”(expr3)< '6' (expr2) which makes that interval empty.

某些值将在“10-16”和“6-14”之间匹配,但仅匹配“12-31”以内的值,因此只有您要查找的范围的大约一半。一月到九月之间的任何内容都会有第一个字符“0”,因此不会在该范围内。

您可以使用两位数的月份数字将第二场比赛分成两部分:

CASE
   WHEN reg_con * tagg_reading <60 and to_char(read_date, 'MM-DD') BETWEEN '06-15' AND '10-15' then 'Y'
   WHEN reg_con * tagg_reading <90 and to_char(read_date, 'MM-DD') BETWEEN '01-01' AND '06-14' then 'Y'
   WHEN reg_con * tagg_reading <90 and to_char(read_date, 'MM-DD') BETWEEN '10-16' AND '12-31' then 'Y'
ELSE 'N'
END as Keep_Flag

或者您可以保留一个范围,但使用

NOT BETWEEN
来排除“06-15”到“10-16”范围:

CASE
   WHEN reg_con * tagg_reading <60 and to_char(read_date, 'MM-DD') BETWEEN '06-15' AND '10-15' then 'Y'
   WHEN reg_con * tagg_reading <90 and to_char(read_date, 'MM-DD') NOT BETWEEN '06-15' AND '10-15' then 'Y'
ELSE 'N'
END as Keep_Flag

这看起来仍然很奇怪,但是没有样本数据和预期结果,不清楚它是否会达到您真正想要的效果。一般来说,最好将日期与日期(或日期范围)进行比较,但您忽略了年份,这是一个问题。您也可以用季度数字做一些事情,在转换进行比较之前在值中添加天数,但同样不清楚。


0
投票

我尝试重现您的问题,假设 read_date 的格式为 DD-MM-YY。您的查询正在比较字符串。

您可以像这样使用

TO_DATE

TO_DATE(TO_CHAR(read_date, 'MM-DD'), 'MM-DD') BETWEEN TO_DATE('06-15', 'MM-DD') AND TO_DATE('10-15', 'MM-DD') 

对于第二个条件

BETWEEN '10-16' AND '6-14'

您打算添加 10 月 16 日至 6 月 14 日之间的日期还是反之亦然,即 6 月 14 日至 10 月 16 日之间的日期。我假设您想添加 10 月 16 日至 6 月 14 日之间的日期,因为 6 月至 10 月包含在第一个条件。

AND (TO_CHAR(read_date, 'MM-DD') BETWEEN '10-16' AND '12-31' OR TO_CHAR(read_date, 'MM-DD') BETWEEN '01-01' AND '06-14') THEN 'Y'

小提琴

示例输入

身份证 REG_CON TAGG_READING 阅读_日期
1 1 10 24 年 6 月 20 日
2 4 20 24 年 4 月 10 日
3 4 30 24 年 8 月 15 日
4 4 40 24 年 12 月 25 日
5 3 50 24 年 10 月 5 日
SELECT id, reg_con, tagg_reading, read_date,
CASE
    WHEN reg_con * tagg_reading < 60 
         AND TO_CHAR(read_date, 'MM-DD') BETWEEN '06-15' AND '10-15' THEN 'Y'
    WHEN reg_con * tagg_reading < 90 
         AND (TO_CHAR(read_date, 'MM-DD') BETWEEN '10-16' AND '12-31' OR TO_CHAR(read_date, 'MM-DD') BETWEEN '01-01' AND '06-14') THEN 'Y'
    ELSE 'N'
END AS Keep_Flag
FROM test;

输出

身份证 REG_CON TAGG_READING 阅读_日期 KEEP_FLAG
1 1 10 24 年 6 月 20 日
2 4 20 24 年 4 月 10 日
3 4 30 24 年 8 月 15 日 N
4 4 40 24 年 12 月 25 日 N
5 3 50 24 年 10 月 5 日 N
© www.soinside.com 2019 - 2024. All rights reserved.