本月在Amazon Redshift PostgreSQL中剩余的工作日

时间:2016-03-18 22:33:51

标签: mysql postgresql datetime amazon-redshift date-manipulation

我想找到一种方法,使用Redshift PostgreSQL确定此日历月中剩余的工作日数。我目前有一个朋友写的MySQL版本。我不太了解它是如何写成甚至翻译成另一种方言的。但如果有人可以帮助翻译它,这将是一个非常有用的工具!

输出应该像excel中的networkdays()函数一样运行。在此函数中,提供begin_date和end_date作为函数的参数。它计算包括开始日期和结束日期之间的工作日数(非周末日历日)。

这是当前的MySQL:

SELECT 1 AS pk ,COUNT(*) AS remaining
FROM (
    SELECT WEEKDAY(DATE(DATE_FORMAT(CONVERT_TZ(NOW(), 'UTC', 'PST8PDT'), '%Y-%m-01') + INTERVAL (a.num-1) DAY)) AS weekdays
        FROM (
        SELECT @row := @row + 1 AS num
        FROM schema.table t, (SELECT @row := 0) r
    ) a
        WHERE a.num >= DAY(CONVERT_TZ(NOW(), 'UTC', 'PST8PDT'))
        AND a.num <= DAY((DATE_FORMAT(CONVERT_TZ(NOW(), 'UTC', 'PST8PDT'), '%Y-%m-01') + INTERVAL 1 MONTH) - INTERVAL 1 DAY)
) b
WHERE b.weekdays NOT IN (0,6)

任何帮助都会很棒!

4 个答案:

答案 0 :(得分:0)

为了计算工作日,您需要使用date_trunc()函数了解当月的第一天的日期start_date)。之后,您需要使用extract()函数获得特定月份的天数month_last_day),此处有wiki page。最后,使用generate_series()日期和start_date号码排除使用date_part()功能的周末日期month_last_day天可以CREATE OR REPLACE FUNCTION extract_month_business_days(d DATE, count_remaining BOOLEAN) RETURNS INTEGER AS $$ DECLARE start_date DATE; month_last_day INTEGER; result INTEGER; BEGIN IF count_remaining THEN start_date = d; ELSE start_date = date_trunc('month',d); END IF; month_last_day = extract(DAY FROM date_trunc('month',d) + INTERVAL '1 MONTH - 1 day'); SELECT count(*) INTO result FROM generate_series(0,(month_last_day - extract(DAY FROM start_date))::INTEGER) day WHERE date_part('dow', start_date + day) NOT IN (0,6); RETURN result; END; $$ LANGUAGE plpgsql; 天。

WITH t(dates) AS ( VALUES
  ('2016-02-18'::DATE),
  ('2016-03-18'::DATE),
  ('2016-04-18'::DATE),
  ('2016-05-18'::DATE)
)
SELECT
  to_char(dates,'Month YY') AS month,
  extract_month_business_days(dates,FALSE) AS number_business_days,
  extract_month_business_days(dates,TRUE) AS remaining_business_days
FROM t;

    month     | number_business_days | remaining_business_days 
--------------+----------------------+-------------------------
 February  16 |                   21 |                       8
 March     16 |                   23 |                      10
 April     16 |                   21 |                      10
 May       16 |                   22 |                      10
(4 rows)

结果:

generate_series()

更新 - REDSHIFT EDITION

正如 @John 所指出的,CREATE OR REPLACE FUNCTION extract_month_business_days(d DATE, count_remaining BOOLEAN) RETURNS INTEGER AS $$ DECLARE start_date DATE; month_last_day INTEGER; result INTEGER; i INTEGER; BEGIN result = 0; IF count_remaining THEN start_date = d; ELSE start_date = date_trunc('month',d); END IF; month_last_day = extract(DAY FROM date_trunc('month',d) + INTERVAL '1 MONTH - 1 day'); result = 0; FOR i IN 0..(month_last_day - extract(DAY FROM start_date))::INTEGER LOOP IF (date_part('dow', start_date + i) NOT IN (0,6)) THEN result = result + 1; END IF; END LOOP; RETURN result; END; $$ LANGUAGE plpgsql; 在AWS Redshift中不可用,函数定义如下:

var select = document.getElementById("weaponbody");
while (select.firstChild) {
    select.removeChild(select.firstChild);
}

答案 1 :(得分:0)

不需要任何功能,您可以使用单个SQL语句执行此操作:

SELECT count(*)
FROM generate_series(CURRENT_TIME,
                     date_trunc('month', CURRENT_TIME) + interval '1 month - 1 day',
                     interval '1 day') days(d)
WHERE extract(dow from d) NOT IN (0, 6);

当然,如果需要,您可以将其包装在SQL函数中。考虑到您在当月剩余工作日的要求,您无需指定任何参数。

答案 2 :(得分:0)

数据仓库的一个流行理念是创建一个calendar表,其中包含所有日期(或至少与公司相关的日期),以及以下标志:

  • 公众假期
  • 工作日
  • 每月的第一天(工作)
  • 每月的最后一天(工作)
  • 月号
  • 周数
  • 日期编号

虽然其中许多值可以通过日期函数计算,但通常可以更容易地加入calendar表来执行某些日期函数。

在计算剩余工作日的情况下,只需要计算calendar表中设置is_work_day标志所需范围内的行数。这可以通过JOIN或子查询来完成。

不像其中一些查询那样花哨但通常更容易维护。此外,Amazon Redshift不支持generate_series功能,因此通常都是可能的。

另见:

答案 3 :(得分:0)

我的答案包括只有一大堆交易的桌子,在你关心的月份中每天至少有一个。对我来说幸运的是,我们的系统允许用户在将来安排交易,因此我可以ping它以获得一些简单的日期逻辑。

TemplateField