Oracle SQL 统计同月的星期几

Oracle SQL counting the days of the week of the same month

如何计算用户将提供给我的 SQL 查询的特定月份的每周天数?例如,如果用户输入 2021 年 4 月,则结果将为:

如果用户输入 2021 年 5 月,结果将为:

我认为这是您要查找的查询:

SELECT WEEK AS WEEK_NUMBER, COUNT(*) AS WEEK_DAYS
FROM (SELECT TO_CHAR(FIRST_DAY + (LEVEL-1), 'IW') AS WEEK
      FROM (SELECT supplied_date AS FIRST_DAY, LAST_DAY(supplied_date) - SUPPLIED_DATE+1 AS DAYS
            FROM (SELECT TO_DATE('05/2021', 'MM/YYYY') AS SUPPLIED_DATE
                  FROM DUAL))
CONNECT BY LEVEL <= DAYS)
GROUP BY WEEK
ORDER BY WEEK;

只需将内部 TO_DATE 替换为您的日期即可。

编辑 1:附加列(查看评论)

SELECT MONTH_NAME, WEEK AS WEEK_NUMBER, COUNT(*) AS WEEK_DAYS
FROM (SELECT TO_CHAR(FIRST_DAY, 'MONTH') AS MONTH_NAME, TO_CHAR(FIRST_DAY + (LEVEL-1), 'IW') AS WEEK
      FROM (SELECT supplied_date AS FIRST_DAY, TO_CHAR(LAST_DAY(supplied_date), 'DD') AS DAYS
            FROM (SELECT TO_DATE('05/2021', 'MM/YYYY') AS SUPPLIED_DATE
                  FROM DUAL))
CONNECT BY LEVEL <= DAYS)
GROUP BY MONTH_NAME, WEEK
ORDER BY WEEK;

注意:我还更改了计算该月天数的方式。

您可以使用以下方法生成周数(无需使用任何聚合):

WITH input ( month ) AS (
  SELECT DATE '2021-04-01' FROM DUAL
),
weeks_of_month ( month_start, week_start, end_day ) AS (
  SELECT TRUNC( month, 'MM' ),
         TRUNC( month, 'IW' ),
         LAST_DAY( TRUNC( month ) )
  FROM   input
UNION ALL
  SELECT month_start,
         week_start + INTERVAL '7' DAY,
         end_day
  FROM   weeks_of_month
  WHERE  week_start + INTERVAL '7' DAY <= end_day
)
SELECT TO_CHAR( week_start, 'IW' ) AS iso_week,
       GREATEST( month_start, week_start ) AS first_day_of_week,
       LEAST( end_day, week_start + INTERVAL '6' DAY ) AS last_day_of_week,
       LEAST( end_day + 1, week_start + INTERVAL '7' DAY )
       - GREATEST( month_start, week_start ) AS days
FROM   weeks_of_month;

哪些输出(NLS_DATE_FORMAT 设置为 YYYY-MM-DD (DY)):

ISO_WEEK FIRST_DAY_OF_WEEK LAST_DAY_OF_WEEK DAYS
13 2021-04-01 (THU) 2021-04-04 (SUN) 4
14 2021-04-05 (MON) 2021-04-11 (SUN) 7
15 2021-04-12 (MON) 2021-04-18 (SUN) 7
16 2021-04-19 (MON) 2021-04-25 (SUN) 7
17 2021-04-26 (MON) 2021-04-30 (FRI) 5

db<>fiddle here

这里直接计算一下。输入以字符串形式给出,例如May 2021;您可以在其位置使用绑定变量。请记住用户可能处于非英语地区的可能性;只要他们使用当地语言将月份传递给查询,一切都应该正常。

with
  inputs    (mth) as (select 'May 2021' from dual)
, first_day (dt)  as (select to_date(mth, 'fmMonth yyyy') from inputs)
, mondays (dt, ord, lst) as (
    select  trunc(dt, 'iw') + 7 * (level - 1), level, max(level) over ()
    from    first_day
    connect by level <= 1 + (trunc(add_months(dt, 1), 'iw') - trunc(dt, 'iw')) / 7
  )
select to_number(to_char(dt, 'iw')) as week_number,
       case ord when 1   then dt + 7 - trunc(dt + 7, 'mm')
                when lst then last_day(dt) + 1 - dt
                         else 7 end as week_days
from   mondays
order  by week_number
;

WEEK_NUMBER  WEEK_DAYS
----------- ----------
         17          2
         18          7
         19          7
         20          7
         21          7
         22          1