【问题标题】:Oralce 12c Loop Through Multiple Start and End Dates and Find Specific Days Between ThemOracle 12c 循环遍历多个开始和结束日期并查找它们之间的特定日期
【发布时间】:2021-09-11 23:19:09
【问题描述】:

我有两个主表,其中一个包含上课的开始和结束日期以及一周中的哪几天。另一张表记录了老师出勤时的出勤情况。我需要做的是每节课我都需要一个老师没有出席的日期列表。以下是我到目前为止适用于一门课程的内容,但我不确定如何遍历每门课程 (CRN) 的“with 子句”。

用于测试的代码

CREATE TABLE SSRMEET 
(
  SSRMEET_TERM_CODE VARCHAR2(6 CHAR) NOT NULL 
, SSRMEET_CRN VARCHAR2(5 CHAR) NOT NULL 
, SSRMEET_START_DATE DATE NOT NULL 
, SSRMEET_END_DATE DATE NOT NULL 
, SSRMEET_SUN_DAY VARCHAR2(1 CHAR) 
, SSRMEET_MON_DAY VARCHAR2(1 CHAR) 
, SSRMEET_TUE_DAY VARCHAR2(1 CHAR) 
, SSRMEET_WED_DAY VARCHAR2(1 CHAR) 
, SSRMEET_THU_DAY VARCHAR2(1 CHAR) 
, SSRMEET_FRI_DAY VARCHAR2(1 CHAR) 
, SSRMEET_SAT_DAY VARCHAR2(1 CHAR)
,SSRMEET_SURROGATE_ID VARCHAR2(20 CHAR)
)
CREATE TABLE SORATRK 
(
  SORATRK_SEQ_NO NUMBER(19, 0) NOT NULL 
, SORATRK_TERM_CODE VARCHAR2(6 CHAR) NOT NULL 
, SORATRK_CRN VARCHAR2(5 CHAR) 
)
CREATE TABLE SORSATR 
(
  SORSATR_SURROGATE_ID_SSRMEET NUMBER(19, 0) NOT NULL 
, SORSATR_PIDM NUMBER(9, 0) NOT NULL 
, SORSATR_MEET_DATE DATE NOT NULL 
)

Insert into SSRMEET (SSRMEET_TERM_CODE,SSRMEET_CRN,SSRMEET_START_DATE,SSRMEET_END_DATE,SSRMEET_SUN_DAY,SSRMEET_MON_DAY,SSRMEET_TUE_DAY,SSRMEET_WED_DAY,SSRMEET_THU_DAY,SSRMEET_FRI_DAY,SSRMEET_SAT_DAY,SSRMEET_SURROGATE_ID) values ('202131','112',to_date('07-JUN-21','DD-MON-RR'),to_date('15-JUL-21','DD-MON-RR'),null,'M','T','W','R',null,null,276309);
Insert into SSRMEET (SSRMEET_TERM_CODE,SSRMEET_CRN,SSRMEET_START_DATE,SSRMEET_END_DATE,SSRMEET_SUN_DAY,SSRMEET_MON_DAY,SSRMEET_TUE_DAY,SSRMEET_WED_DAY,SSRMEET_THU_DAY,SSRMEET_FRI_DAY,SSRMEET_SAT_DAY,SSRMEET_SURROGATE_ID) values ('202131','856',to_date('12-JUL-21','DD-MON-RR'),to_date('06-AUG-21','DD-MON-RR'),null,'M','T','W','R',null,null,278403);


Insert into SORATRK (SORATRK_SEQ_NO,SORATRK_TERM_CODE,SORATRK_CRN) values (20,'202131','112');
--Insert into SORATRK (SORATRK_SEQ_NO,SORATRK_TERM_CODE,SORATRK_CRN) values (21,'202131','856');

Insert into SORSATR (SORSATR_SURROGATE_ID_SSRMEET,SORSATR_PIDM,SORSATR_MEET_DATE) values (276309,9934,to_date('07-JUN-21','DD-MON-RR'));
Insert into SORSATR (SORSATR_SURROGATE_ID_SSRMEET,SORSATR_PIDM,SORSATR_MEET_DATE) values (276309,9934,to_date('09-JUN-21','DD-MON-RR'));

需要的样本输出

与插入语句中的一个 CRN 一起工作的当前代码。有一个注释掉的第二个插入。

with attend as (
  select :crn  crn, 
            (select ssrmeet_surrogate_id
                                    from ssrmeet 
                                    join soratrk on soratrk_term_code = :term_select
                                    and soratrk_crn = ssrmeet_crn
                                    where ssrmeet_crn = :crn 
                                    and ssrmeet_term_code = :term_select) ssrmeet_surrogate_id,
                    
            (select ssrmeet_start_date - 1 
                    from ssrmeet 
                    join soratrk on soratrk_term_code = :term_select
                    and soratrk_crn = ssrmeet_crn
                    where ssrmeet_crn = :crn 
                    and ssrmeet_term_code = :term_select)  + level days_no_attendance_taken
   from   dual
  connect by level <= ((select nvl((select ssrmeet_end_date
                                        from ssrmeet 
                                        join soratrk on soratrk_term_code = :term_select
                                        and soratrk_crn = ssrmeet_crn
                                        where ssrmeet_crn = :crn 
                                        and ssrmeet_term_code = :term_select
                                        and ssrmeet_end_date < sysdate)
                                , sysdate) 
                    from dual)
- 
(select ssrmeet_start_date
                    from ssrmeet 
                    join soratrk on soratrk_term_code = :term_select
                    and soratrk_crn = ssrmeet_crn
                    where ssrmeet_crn = :crn 
                    and ssrmeet_term_code = :term_select)

  )
)
select :crn crn, days_no_attendance_taken 
  from   attend
where to_char ( 
days_no_attendance_taken, 
'fmday', 
'nls_date_language = english' 
  ) in ('monday','tuesday','wednesday','thursday')

minus

 select distinct :crn crn, sorsatr_meet_date 
from sorsatr
join ssrmeet on sorsatr_surrogate_id_ssrmeet = ssrmeet_surrogate_id
and ssrmeet_crn = :crn
order by 2

我正在关注此示例,但需要它在 with 子句中按级别连接中的多个开始和结束日期工作。

with rws as (
  select date'2020-12-31' + level dt
  from   dual
  connect by level <= (
    date'2022-01-01' - date'2021-01-01'
  )
)
  select dt
  from   rws
  where  to_char ( 
    dt, 
    'fmday', 
    'nls_date_language = English' 
  ) = 'monday';
  
DT            
04-Jan-2021    
11-Jan-2021    
...
20-Dec-2021    
27-Dec-2021    

52 rows selected. 

【问题讨论】:

  • 请提供样本数据和期望的结果。
  • 我添加了示例数据和所需的输出。
  • 请提供表格结构并更详细地阐明您的需求逻辑
  • “我添加了示例数据和所需的输出” 示例数据,如实际表中的 DDL 和 INSERT 语句......在代码中,而不是图像中,因此人们可以使用它来测试。见stackoverflow.com/help/minimal-reproducible-example
  • 埃德史蒂文斯感谢您的评论。我有创建和插入语句,以便您进行测试。 :-)

标签: sql oracle date


【解决方案1】:

Oracle 社区的 Frank Kulash 给了我这个有效的答案。

 SELECT   m1.ssrmeet_crn
,    c.a_date
FROM     ssrmeet m1
CROSS APPLY (
            SELECT m1.ssrmeet_start_date + LEVEL - 1 AS a_date
        FROM    dual
        CONNECT BY  LEVEL <=  1 + LEAST ( m1.ssrmeet_end_date
                        , SYSDATE - 1
                        )
                    - m1.ssrmeet_start_date
        )    c
WHERE   CASE TO_CHAR (c.a_date, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH')
       WHEN 'Sun' THEN ssrmeet_sun_day
       WHEN 'Mon' THEN ssrmeet_mon_day
       WHEN 'Tue' THEN ssrmeet_tue_day
       WHEN 'Wed' THEN ssrmeet_wed_day
       WHEN 'Thu' THEN ssrmeet_thu_day
       WHEN 'Fri' THEN ssrmeet_fri_day
       WHEN 'Sat' THEN ssrmeet_sat_day
     END                  IS NOT NULL
AND  m1.ssrmeet_crn       = :crn
AND  m1.ssrmeet_term_code = :term_select
  MINUS
SELECT   m2.ssrmeet_crn
,    a.sorsatr_meet_date
FROM     ssrmeet m2
JOIN     sorsatr a ON a.sorsatr_surrogate_id_ssrmeet = m2.ssrmeet_surrogate_id
  --
ORDER BY ssrmeet_crn
,        a_date
;    enter code here

【讨论】:

    猜你喜欢
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    相关资源
    最近更新 更多