Oracle 星期几(无字符串比较)

UpT*_*ide 0 sql oracle oracle11g

我会在前面说我发现的所有文档都不适用于我的 Oracle 版本: https: //docs.oracle.com/cd/E51711_01/DR/WeekDay.html; https://docs.oracle.com/cd/E37483_01/server.751/es_eql/src/ceql_functions_date_extract.html

或者我可以使用的函数参考不要提及星期几: https ://docs.oracle.com/cd/B28359_01/server.111/b28286/functions052.htm#SQLRF00639

所以我只是想办法使用to_char来做到这一点,然后进行 varchar2 比较。如果可能的话,我想坚持使用日期格式。

到目前为止这是我的sql

select dateSold from sales
where extract(dateSold, day_of_week) in (1, 3, 4, 7)

SQL Error: ORA-00904: "DAY_OF_WEEK": invalid identifier
Run Code Online (Sandbox Code Playgroud)

Ale*_*ole 5

您需要使用to_char()来获取天数,但您可以将其转换为数字:

select dateSold, sum(quantity) from sales
where to_number(to_char(dateSold, 'D')) in (1, 3, 4, 7)
Run Code Online (Sandbox Code Playgroud)

但D它依赖于 NLS,因此如果您在美国和法国的会话中运行此命令,您会得到不同的结果。这可能就是您看到字符串比较的原因,因为您至少可以更多地控制:

select dateSold, sum(quantity) from sales
where to_char(dateSold, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') in ('MON', 'WED', 'THU', 'SUN')
Run Code Online (Sandbox Code Playgroud)

要查看 NLS 设置造成的差异,这会显示D相同DY数据和查询的值,就像在美国运行一样:

alter session set nls_territory = 'AMERICA';
alter session set nls_language = 'ENGLISH';

with cte (dateSold) as (
  select date '2018-08-01' + level - 1 from dual connect by level <= 7
)
select dateSold,
  to_number(to_char(dateSold, 'D')) as d,
  to_char(dateSold, 'DY') as dy,
  to_char(dateSold, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') as dy_english
from cte;

DATESOLD           D DY           DY_ENGLISH  
--------- ---------- ------------ ------------
01-AUG-18          4 WED          WED         
02-AUG-18          5 THU          THU         
03-AUG-18          6 FRI          FRI         
04-AUG-18          7 SAT          SAT         
05-AUG-18          1 SUN          SUN         
06-AUG-18          2 MON          MON         
07-AUG-18          3 TUE          TUE         
Run Code Online (Sandbox Code Playgroud)

然后就像在法国运行一样:

alter session set nls_territory = 'FRANCE';
alter session set nls_language = 'FRENCH';

with cte (dateSold) as (
  select date '2018-08-01' + level - 1 from dual connect by level <= 7
)
select dateSold,
  to_number(to_char(dateSold, 'D')) as d,
  to_char(dateSold, 'DY') as dy,
  to_char(dateSold, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') as dy_english
from cte;

and the same thing as if run in the USA:

DATESOLD          D DY               DY_ENGLISH  
-------- ---------- ---------------- ------------
01/08/18          3 MER.             WED         
02/08/18          4 JEU.             THU         
03/08/18          5 VEN.             FRI         
04/08/18          6 SAM.             SAT         
05/08/18          7 DIM.             SUN         
06/08/18          1 LUN.             MON         
07/08/18          2 MAR.             TUE         
Run Code Online (Sandbox Code Playgroud)

请注意,日期数字和名称/缩写非常不同,因此尝试将它们与固定值进行比较(无论in (1, 3, 4, 7)是否使用字符串文字日期名称)都无法可靠匹配。

将日期语言强制为英语可以使比较安全。(当然,或者任何其他语言 - 字符串文字值只需与您为第三个参数选择的语言相匹配to_char()。)