【问题标题】:Show number of weeks in a given month显示给定月份的周数
【发布时间】:2014-05-23 16:44:20
【问题描述】:

所以,过去几天我一直被这个问题困扰,但我仍然无法提出解决方案。

我想将给定的月份分组为几周,这很容易,但(可怕的)业务要求是将一天也视为一周,如果它 周一至周日之间的任何一天。一周的结束日将是星期日。

例如,我将在 8 月份进行演示。根据业务需求,这就是给定月份的数据显示方式

First week  - August 1st to August 2nd, 2015
Second week - August 3nd to August 9th, 2015
Third week  - August 10th to August 16th, 2015
Fourth week - August 17th to August 23rd, 2015
Fifth week  - August 24th to August 30th, 2015
Sixth week  - August 31st, 2015

由于出现第六周,我完全不知道如何处理该问题。 我在 AskTom 上遇到了这个查询,它显示 5 周,但在 8 月 31 日重置回 1。此外,查询看起来不是一个优雅的解决方案。

select dt, to_char( dt+1, 'w' )
     from ( select to_date('1-aug-2015')+rownum dt
              from all_objects
                    where rownum < 31 );

寻找有关问题的建议/见解。 谢谢

【问题讨论】:

    标签: sql oracle oracle10g


    【解决方案1】:
    WITH x (dt)
         AS (    SELECT DATE '2015-08-01' + LEVEL - 1 dt
                   FROM DUAL
             CONNECT BY DATE '2015-08-01' + LEVEL - 1 < DATE '2015-09-01')
    SELECT dt,
           SUM (
              CASE
                 WHEN TO_CHAR (dt, 'd') = '2'      --if the day is monday
                   OR TO_CHAR (dt, 'fmdd') = '1'   --or if its the first day of the month, assign 1.
                 THEN
                    1
                 ELSE
                    0
              END)
           OVER (ORDER BY dt)
              wk_nr
      FROM x;
    
    1. 首先生成给定月份的所有日期。
    2. 通过将其标记为 1 来确定每周的开始和月份的开始。将其余天标记为 0。这里 to_char(dt,'d') 给出 2 表示星期一。但可能会根据会话的 NLS 区域而变化。
    3. 现在您有了每周的开始时间,使用 SUM 来计算累积总和。这将为您提供所需的周数。

    示例fiddle


    更新

    看起来 10g 不支持带有 CTE 名称的 column alias。删除它并尝试。

    WITH x 
         AS (SELECT ....
    

    【讨论】:

    • 很好的解决方案!这就是我一直在寻找的。 Fiddle 显示所需的结果,但我似乎无法在 10G 版本上运行它。它在第 1 行抛出 ORA-32033: unsupported column aliasing 错误。
    【解决方案2】:
       --TRY THIS
    

    --我是为 SYSDATE 做的。

       SELECT DT,
       CASE
           WHEN TO_CHAR(DT+1, 'W')='1'
                AND SUBSTR(DT,1,2)>'24' THEN '6'
           ELSE TO_CHAR(DT+1, 'W')
       END
       FROM
        (SELECT TO_DATE(SYSDATE)+ROWNUM DT FROM ALL_OBJECTS 
         );
    

    --您的示例中的查询。

      SELECT DT,CASE WHEN TO_CHAR( DT+1, 'w' )='1' AND SUBSTR( DT,1,2)>'24' THEN '6' ELSE    TO_CHAR( DT+1, 'w' ) END
     from ( select to_date('1-aug-2015')+rownum dt
            FROM ALL_OBJECTS
            WHERE ROWNUM < 31
          );
    

    【讨论】:

    • 第二个查询对您来说效果很好 +1,但就像我说的那样,我真的不想将此查询作为公认的解决方案。不过谢谢。我会等到我得到更复杂的查询作为解决方案。
    • 我认为这是最好的方法,否则你可能不得不使用一些分析函数
    • 这正是我想要的。
    • 这对其他月份有效吗?看起来它只适用于这个月。
    【解决方案3】:

    一个表变量真的很好用:

    declare @calendar table (WkDay date, DayOfWk int, YR INT, MO INT)
    DECLARE @BEG_DT DATE
    SET @BEG_DT='2016-12-01'
    WHILE @BEG_DT <='2250-01-01'
    BEGIN
        INSERT INTO @calendar VALUES (@BEG_DT, DATEPART(WEEKDAY,@BEG_DT), DATEPART(YEAR,@BEG_DT), DATEPART(MONTH,@BEG_DT))
    
        SET @BEG_DT=DATEADD(DAY,1,@BEG_DT)
    END
    
    SELECT *
    FROM @calendar
    

    然后计算“1”dayofwk 的数量,你会得到给定月份的周数

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      相关资源
      最近更新 更多