我想找到一种方法,使用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)
任何帮助都会很棒!
答案 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()
正如 @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