使用Oracle SQL,如何输出星期几和星期几?

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

使用 Oracle SQL,如何创建以下结果集:

  • 星期几的数字 (1-7)
  • 当天的名称(星期一、星期二、星期三等)

例如:

日期名称
1 星期一
2 星期二
3 周三
4 星期四
5 周五
6 星期六
7 周日
sql oracle
6个回答
28
投票

Florin 的答案是我会如何做,但你需要小心 NLS 设置。一周中的哪一天受到 NLS 区域的影响,所以如果我像在美国一样运行它,它会起作用:

alter session set nls_territory = 'AMERICA';

select to_char(sysdate, 'D') as d, to_char(sysdate, 'Day') as day from dual;

D DAY
- ------------------------------------
6 Friday

select level as dow,
    to_char(trunc(sysdate ,'D') + level, 'Day') as day
from dual
connect by level <= 7;

DOW DAY
--- ------------------------------------
  1 Monday
  2 Tuesday
  3 Wednesday
  4 Thursday
  5 Friday
  6 Saturday
  7 Sunday

但是在英国运行的相同查询是休息日:

alter session set nls_territory = 'UNITED KINGDOM';

select to_char(sysdate, 'D') as d, to_char(sysdate, 'Day') as day from dual;

D DAY
- ------------------------------------
5 Friday

select level as dow,
    to_char(trunc(sysdate ,'D') + level, 'Day') as day
from dual
connect by level <= 7;

DOW DAY
--- ------------------------------------
  1 Tuesday
  2 Wednesday
  3 Thursday
  4 Friday
  5 Saturday
  6 Sunday
  7 Monday

...我需要调整计算来纠正这一点:

select level as dow,
    to_char(trunc(sysdate ,'D') + level - 1, 'Day') as day
from dual
connect by level <= 7;

DOW DAY
--- ------------------------------------
  1 Monday
  2 Tuesday
  3 Wednesday
  4 Thursday
  5 Friday
  6 Saturday
  7 Sunday

如果需要,您还可以单独指定日期名称所使用的语言:

select level as dow,
    to_char(trunc(sysdate ,'day') + level - 1, 'Day',
        'NLS_DATE_LANGUAGE=FRENCH') as day
from dual
connect by level <= 7;

DOW DAY
--- --------------------------------
  1 Lundi
  2 Mardi
  3 Mercredi
  4 Jeudi
  5 Vendredi
  6 Samedi
  7 Dimanche

to_char()
以及
nls_date_language
星期几的文档,以及全球化支持指南中的更多信息。


4
投票

尝试从日期获取天数时,您可以避免使用

NLS_TERRITORY
TO_CHAR(dt, 'D')
设置引发的问题,而是将这一天与 ISO 周的开始时间(始终是星期一午夜)进行比较:

SELECT TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') + 1 AS day_number,
       TO_CHAR(SYSDATE, 'fmDAY') AS day
FROM   DUAL;

哪个输出:

DAY_NUMBER 白天
5 周五

注意:您还可以使用

fmDAY
自动删除日期名称中的尾随空格。如果您使用
DAY
(不带
fm
修饰符),则所有日期名称将被填充为相等的长度;对于英语来说,这意味着
Friday   
将被右填充到与
Wednesday
相同的长度。


使用 ISO 周与使用

TO_CHAR
进行比较:

ALTER SESSION SET NLS_TERRITORY = 'GERMANY';

SELECT TO_CHAR(SYSDATE, 'D') AS dn_tochar
       TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') + 1 AS dn_isoweek
FROM   DUAL

输出:

DN_TOCHAR DN_ISOWEEK
5 5

哪个好;由于 Oracle 认为德国的一周从星期一开始,因此星期五是一周的第五天。

但是在不同的地区进行相同的查询:

ALTER SESSION SET NLS_TERRITORY = 'BANGLADESH';

SELECT TO_CHAR(SYSDATE, 'D') AS dn_tochar
       TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') + 1 AS dn_isoweek
FROM   DUAL

输出:

DN_TOCHAR DN_ISOWEEK
1 5

并且没有给出与

TO_CHAR
版本相同的答案,因为 Oracle 认为孟加拉国的一周从周五开始,因此这将是一周的第一天。

同样,在其他国家/地区,埃及的一周从周六开始,美国的一周从周日开始,因此如果您使用

TO_CHAR
,它们的所有值都将关闭;但如果你使用 ISO 周则不然。


但是,如果您只想生成一周中的每一天的 7 行,那么您可以简化问题并使用分层查询来生成日期数字,然后从 ISO 周的开始位置偏移日期:

SELECT LEVEL AS day_number,
       TO_CHAR(
         TRUNC(SYSDATE, 'IW') + LEVEL - 1,
         'fmDAY',
         'NLS_DATE_LANGUAGE=English'
       ) AS day
FROM   DUAL
CONNECT BY LEVEL <= 7;

始终输出:

DAY_NUMBER 白天
1 周一
2 星期二
3 星期三
4 星期四
5 周五
6 星期六
7 周日

db<>小提琴这里


2
投票
select level as dow, 
    to_char(level+trunc(sysdate,'D'),'Day') as day
from dual
connect by level <= 7;

1
投票

无需更改会话

 CASE 
    WHEN to_char(sysdate, 'd')-1 = 0 THEN 7 
    ELSE to_char(sysdate, 'd')-1 
 END 

0
投票

在 Oracle Database 23ai 中,您可以创建一个 枚举域来列出一周中的日子

create domain days_of_week as enum ( 
  monday,   tuesday, wednesday, 
  thursday, friday,  saturday, 
  sunday 
);

select * from days_of_week;

ENUM_NAME ENUM_VALUE
--------- ----------
MONDAY             1
TUESDAY            2
WEDNESDAY          3
THURSDAY           4
FRIDAY             5
SATURDAY           6
SUNDAY             7

值从 1 开始,每一项增加 1。您可以提供自己的起始值。例如,从星期一开始,其值为零:

drop domain if exists days_of_week;
create domain days_of_week as enum ( 
  monday = 0, tuesday, wednesday, 
  thursday,   friday,  saturday, 
  sunday 
);

select * from days_of_week;

ENUM_NAME ENUM_VALUE
--------- ----------
MONDAY             0
TUESDAY            1
...
SUNDAY             6

或者您可以使用每一天的字符串值。这里的值是日期名称的两个字母缩写:

drop domain if exists days_of_week;
create domain days_of_week as enum ( 
  monday    = 'MO', tuesday   = 'TU', 
  wednesday = 'WE', thursday  = 'TH', 
  friday    = 'FR', saturday  = 'SA', 
  sunday    = 'SU'
);

select * from days_of_week;

ENUM_NAME EN
--------- --
MONDAY    MO
TUESDAY   TU
WEDNESDAY WE
THURSDAY  TH
FRIDAY    FR
SATURDAY  SA
SUNDAY    SU

您还可以将多个名称与一个值链接起来。内置枚举

day_enum_d
列出了每个名称的全名和三个字母缩写:

select * from sys.day_enum_d;

ENUM_NAME ENUM_VALUE
--------- ----------
MONDAY             1
MON                1
TUESDAY            2
TUE                2
WEDNESDAY          3
...

-2
投票
Select 1, 'Monday' from dual union all select 2, 'Tuesday' from dual ...
© www.soinside.com 2019 - 2024. All rights reserved.