【问题标题】:get second and fourth saturday along with all sundays of the previous month in oracle在 oracle 中获取第二个和第四个星期六以及上个月的所有星期日
【发布时间】:2019-08-06 18:42:25
【问题描述】:

我有以下查询,它给出了上个月的第二个和第四个星期六以及上个月的所有星期日:

SELECT to_char(NEXT_DAY(NEXT_DAY(NEXT_DAY(NEXT_DAY(TRUNC((SELECT LAST_DAY(ADD_MONTHS(sysdate,-1)) FROM DUAL), 'MONTH') - 1, 'SATURDAY'), 'SATURDAY'),'SATURDAY'),'SATURDAY'),'YYYYMMDD') SECOND_SATURDAY 
FROM DUAL
UNION ALL
SELECT to_char(NEXT_DAY(NEXT_DAY(TRUNC((SELECT LAST_DAY(ADD_MONTHS(sysdate,-1)) FROM DUAL), 'MONTH') - 1, 'SATURDAY'),'SATURDAY'),'YYYYMMDD') SECOND_SATURDAY 
FROM DUAL
UNION ALL
select distinct day_date from
(SELECT to_char(NEXT_DAY(LEVEL + TRUNC((SELECT LAST_DAY(ADD_MONTHS(sysdate,-1)) FROM DUAL), 'MONTH') - 1,'SUNDAY'),'YYYYMMDD') day_date
FROM DUAL
CONNECT BY LEVEL <=  ADD_MONTHS(TRUNC((SELECT LAST_DAY(ADD_MONTHS(sysdate,-1)) FROM DUAL), 'MONTH'), 1) - TRUNC((SELECT LAST_DAY(ADD_MONTHS(sysdate,-1)) FROM DUAL), 'MONTH'))
where substr(day_date,1,6) in (select to_char((SELECT LAST_DAY(ADD_MONTHS(sysdate,-1)) FROM DUAL),'YYYYMM') from dual)

但我觉得必须有一种更简单的方法可以在 oracle 中获得相同的结果。欢迎在这方面提供任何帮助。我对日期格式的要求是 'YYYYMMDD'。

【问题讨论】:

    标签: sql oracle date-arithmetic


    【解决方案1】:

    由于我误解了问题而进行了编辑:

    我认为您想要以下内容:

    SELECT TO_CHAR(my_date, 'YYYYMMDD') AS my_formatted_date
      FROM (
        SELECT NEXT_DAY(LAST_DAY(ADD_MONTHS(SYSDATE, -2))+7, 'SATURDAY') AS my_date
          FROM dual
         UNION ALL
        SELECT NEXT_DAY(LAST_DAY(ADD_MONTHS(SYSDATE, -2))+21, 'SATURDAY')
          FROM dual
         UNION ALL
        SELECT NEXT_DAY(LAST_DAY(ADD_MONTHS(SYSDATE, -2)), 'SUNDAY') + (LEVEL-1)*7
          FROM dual
       CONNECT BY NEXT_DAY(LAST_DAY(ADD_MONTHS(SYSDATE, -2)), 'SUNDAY') + (LEVEL-1)*7 < TRUNC(SYSDATE, 'MONTH')
    );
    

    在查询的第一部分中,我确定上个月的最后一天,然后得到该日期后至少一周后的第一个星期六(该月的第二个星期六将是从 8 号到14 号)。然后我得到第一个星期六在上个月的最后一天后至少三周(第四个星期六将是从 22 日到 28 日)。最后,我循环遍历上个月的星期日,从上个月最后一天(即两个月前)之后的第一个星期日开始。你也可以使用NEXT_DAY(TRUNC(ADD_MONTHS(SYSDATE, -1) - 1), 'SUNDAY') 代替NEXT_DAY(LAST_DAY(ADD_MONTHS(SYSDATE, -2)), 'SUNDAY')

    MY_FORMA
    --------
    20190209
    20190223
    20190203
    20190210
    20190217
    20190224
    
    6 rows selected.
    

    【讨论】:

    • 这里的星期六是当月的。我想我必须使用 (SYSDATE, -2) 而不是 (SYSDATE, -1)
    • 嗨@katipra,我相信我误解了你的问题。是的,使用ADD_MONTHS(SYSDATE, -2) 而不是ADD_MONTHS(SYSDATE, -1) 来获得所需的答案。
    【解决方案2】:

    比如这里:

    with 
      t1 as (select add_months(trunc(sysdate, 'month'), -1) dt from dual),
      t2 as (
        select dt + level - 1 dt, to_char(dt + level - 1, 'dy', 'nls_date_language=english') dy
          from t1 connect by dt + level - 1 < trunc(sysdate, 'month'))
    select to_char(dt, 'yyyymmdd') dt, dy
      from (
        select dt, dy, sum(case when dy = 'sat' then 1 end) over (order by dt) sm from t2)
      where dy = 'sun' or (dy = 'sat' and sm in (2, 4))
    

    结果:

    DT       DY
    -------- ---
    20190203 sun
    20190209 sat
    20190210 sun
    20190217 sun
    20190223 sat
    20190224 sun
    

    我生成了上个月的所有日期,指定了英文日期名称,有条件地计算星期六并只显示有趣的日期。


    编辑:

    这可行,但有什么办法可以绕过 with 子句,因为我的 父查询来自:with x as ( .... where date in ("required days") 和 ...) 。所以它呈现了一个嵌套的情况。

    是的,您可以轻松转换它,例如这里:

    select to_char(dt, 'yyyymmdd') dt
      from (
        select dt, dn, rank() over (order by mod(dn, 6), dt) rnk
          from (
            select d + level - 1 dt, d + level - trunc(d + level - 1, 'iw') dn
              from (select add_months(trunc(sysdate, 'month'), -1) d from dual)
              connect by level <= add_months(d, 1) - d))
      where dn = 7 or (dn = 6 and rnk in (2, 4)) 
    

    dbfiddle demo

    with 子句使步骤更具可读性。现在我还使用了日期数字和mod() 进行计数,只是为了展示不同的方法,但您可以使用对您来说更清晰的名称(日期名称,sumcount 而不是rank)。

    【讨论】:

    • 这行得通,但是有什么办法可以绕过 with 子句,因为我的父查询是 from: with x as ( .... where date in ("required days") and .. .) .所以它呈现了一个嵌套的情况
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    相关资源
    最近更新 更多