SQL 使用日历 table 确定自月初以来经过的工作日

SQL determine business days passed since beginning of month using calendar table

我有一个日历 table,其中包含所有日期和一个指示其是否为工作日的列。
例如

Date Business_Day
1/1/2021 False
1/2/2021 False
1/3/2021 True

... 我还有另一个带日期的 table,想确定自该月初以来已经过去了多少个工作日。 例如:

Date Business_Days_Passed
1/1/2022 0
1/2/2022 0
1/3/2022 1
1/4/2022 2
1/15/2022 10
2/2/2022 2
2/11/2022 9
2/12/2022 9

有没有办法使用标准 sql 来做到这一点?我正在考虑创建某种 UDF,但可能有更简单的方法吗?这使用雪花所以可以访问所有常见的日期函数和 window/udf 函数

这是一个简单的查询

Select count(c.date) from calendar c 
Join dates_to_check d
Where month(c.date) = month(d.day)
And day(c.date) < day(d.day)
And business_Day = True;

我认为您可以使用简单的 joinwindow function 来完成此操作。我假设您的日期格式为 yyyy-mm-dd,这将允许 left(date,7) 获得 year-month。如果没有,只需使用不同的函数来提取 year-month 以每月汇总。

select a.date, 
       count(b.business_day) over (partition by left(a.date,7) order by a.date) business_days_elapsed
from table a
     left join calendar_table b on a.date=b.date and b.business_day='True'
group by a.date, b.business_day; --in case your data is not deduped before window function is applied

用单曲试试这个,table你可以创建一个视图

create or replace table bus_day as
SELECT column1  Date, column2   Business_Day  from values
('1/1/2021',    'False'),
('1/2/2021',    'False'),
('1/3/2021',    'True'),
('1/4/2021',    'True'),
('1/5/2021',    'True'),
('1/6/2021',    'True'),
('1/7/2021',    'True'),
('2/1/2021',    'True'),
('2/2/2021',    'True'),
('2/3/2021',    'True'),
('2/4/2021',    'True'),
('2/5/2021',    'False'),
('2/6/2021',    'False'),
('2/7/2021',    'True')
;
 
  SELECT DATE,FIRST_DAY_MONTH 
 ,row_number() over (partition by month(to_date(Date,'mm/dd/yyyy')) order by date) as row_number
 ,count_if(business_day ='True') over (partition by month(to_date(Date,'mm/dd/yyyy'))   order by DATE ) count_days
FROM (
  select Date , DATE_TRUNC('month',to_date(Date,'mm/dd/yyyy')) frst_day,
  iff(to_date(Date,'mm/dd/yyyy') = DATE_TRUNC('month',to_date(Date,'mm/dd/yyyy')), 'Y', 'N') first_day_Month , 
  business_day from bus_day order by date
   );

因此,如果您的 dates 有“所有日期”,您可以使用 JOIN,例如:

SELECT d.date,
    count_if(w.business_day) AS business_days_passed
FROM dates_of_interest AS d
JOIN work_days AS w
    ON date_trunc(month, d.date) = date_trunc(month, w.date) 
        AND d.date >= w.date
GROUP BY 1
ORDER BY 1;

但是如果你的日期之间有间隔,就像我的示例数据一样......你会想要 LEFT JOIN 表单..

SELECT d.date,
    count_if(w.business_day) AS business_days_passed
FROM dates_of_interest AS d
LEFT JOIN work_days AS w
    ON date_trunc(month, d.date) = date_trunc(month, w.date) 
        AND d.date >= w.date
GROUP BY 1
ORDER BY 1;

并使用这个美妙的假数据:

WITH work_days(date, business_day) AS (
    SELECT
        DATEADD('day', ROW_NUMBER() OVER (ORDER BY NULL)-1, TO_DATE('1/1/2022', 'mm/dd/yyyy')) AS date
        ,DAYOFWEEKISO(date) < 6 AS business_day
    FROM TABLE(generator(ROWCOUNT => 65))
), dates_of_interest(date) AS (
    SELECT TO_DATE(column1, 'mm/dd/yyyy')
    FROM VALUES 
        ('1/1/2022'),
        ('1/2/2022'),
        ('1/3/2022'),
        ('1/4/2022'),
        ('1/15/2022'),
        ('2/2/2022'),
        ('2/11/2022'),
        ('2/12/2022')
)

我们得到:

DATE BUSINESS_DAYS_PASSED
2022-01-01 0
2022-01-02 0
2022-01-03 1
2022-01-04 2
2022-01-15 10
2022-02-02 2
2022-02-11 9
2022-02-12 9