计算两个日期之间的工作日数
Counting number of weekdays between two dates
我正在尝试获取 plpgsql 中两个日期之间的工作日数。以下是我的代码:
CREATE FUNCTION weekdays(DATE, DATE) RETURNS INTEGER AS
$$
DECLARE
d date := ;
weekdays integer := 0
BEGIN
LOOP
IF select extract(dow from date d) != 6 or select extract(dow from date d) != 0
weekdays := weekdays +1
END IF
d := d + 1;
EXIT WHEN d > ;
END LOOP;
RETURN weekdays;
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE;
但是,我不断收到以下错误:
Unterminated dollar quote started at position 56 in SQL
CREATE FUNCTION weekdays(DATE, DATE) RETURNS INTEGER AS $$ DECLARE d date := .
Expected terminating $$
错误是由于 weekdays integer := 0;
之后缺少 ;
。加上更多此类错误。这将 有效 :
CREATE OR REPLACE FUNCTION weekdays(date, date)
RETURNS integer AS
$func$
DECLARE
d date := ;
weekdays int := 0;
BEGIN
LOOP
IF extract(isodow from d) < 6 THEN -- simpler
weekdays := weekdays + 1;
END IF;
d := d + 1;
EXIT WHEN d > ;
END LOOP;
RETURN weekdays;
END
$func$ LANGUAGE plpgsql IMMUTABLE;
但我建议使用 更简单、更快速的 SQL 函数 :
CREATE OR REPLACE FUNCTION weekdays_sql(date, date)
RETURNS integer AS
$func$
SELECT count(*)::int
FROM generate_series(, , interval '1d') d
WHERE extract(isodow FROM d) < 6;
$func$ LANGUAGE sql IMMUTABLE;
可能会进一步提高大范围的性能。相关:
- How to count days except Sundays between two dates in Postgres?
- Calculate working hours between 2 dates in PostgreSQL
不需要循环,用算术就能找到答案
CREATE OR REPLACE FUNCTION public.weekdays(s date, e date) RETURNS integer
LANGUAGE plpgsql
IMMUTABLE
AS $function$
DECLARE
sd int = extract (isodow from s-1);
ed int = extract (isodow from e);
BEGIN
RETURN - case sd when 7 then 5 when 6 then 5 else sd end
+ case ed when 7 then 5 when 6 then 5 else ed end
+ (e-ed-s+sd+1)/7*5;
END;
$function$;
在我看来没那么复杂,而且也能正常工作。
CREATE OR REPLACE FUNCTION weekdays
(
date1 DATE,
date2 DATE
)
RETURNS INTEGER AS $$
DECLARE weekdays INTEGER;
BEGIN
SELECT COUNT(extract(ISODOW FROM series)) INTO weekdays
FROM generate_series(date1::date, date2::date, '1 day'::interval) series
WHERE extract(ISODOW FROM series) < 6;
RETURN weekdays;
END;
$$ LANGUAGE plpgsql;
我正在尝试获取 plpgsql 中两个日期之间的工作日数。以下是我的代码:
CREATE FUNCTION weekdays(DATE, DATE) RETURNS INTEGER AS
$$
DECLARE
d date := ;
weekdays integer := 0
BEGIN
LOOP
IF select extract(dow from date d) != 6 or select extract(dow from date d) != 0
weekdays := weekdays +1
END IF
d := d + 1;
EXIT WHEN d > ;
END LOOP;
RETURN weekdays;
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE;
但是,我不断收到以下错误:
Unterminated dollar quote started at position 56 in SQL CREATE FUNCTION weekdays(DATE, DATE) RETURNS INTEGER AS $$ DECLARE d date := . Expected terminating $$
错误是由于 weekdays integer := 0;
之后缺少 ;
。加上更多此类错误。这将 有效 :
CREATE OR REPLACE FUNCTION weekdays(date, date)
RETURNS integer AS
$func$
DECLARE
d date := ;
weekdays int := 0;
BEGIN
LOOP
IF extract(isodow from d) < 6 THEN -- simpler
weekdays := weekdays + 1;
END IF;
d := d + 1;
EXIT WHEN d > ;
END LOOP;
RETURN weekdays;
END
$func$ LANGUAGE plpgsql IMMUTABLE;
但我建议使用 更简单、更快速的 SQL 函数 :
CREATE OR REPLACE FUNCTION weekdays_sql(date, date)
RETURNS integer AS
$func$
SELECT count(*)::int
FROM generate_series(, , interval '1d') d
WHERE extract(isodow FROM d) < 6;
$func$ LANGUAGE sql IMMUTABLE;
可能会进一步提高大范围的性能。相关:
- How to count days except Sundays between two dates in Postgres?
- Calculate working hours between 2 dates in PostgreSQL
不需要循环,用算术就能找到答案
CREATE OR REPLACE FUNCTION public.weekdays(s date, e date) RETURNS integer
LANGUAGE plpgsql
IMMUTABLE
AS $function$
DECLARE
sd int = extract (isodow from s-1);
ed int = extract (isodow from e);
BEGIN
RETURN - case sd when 7 then 5 when 6 then 5 else sd end
+ case ed when 7 then 5 when 6 then 5 else ed end
+ (e-ed-s+sd+1)/7*5;
END;
$function$;
在我看来没那么复杂,而且也能正常工作。
CREATE OR REPLACE FUNCTION weekdays
(
date1 DATE,
date2 DATE
)
RETURNS INTEGER AS $$
DECLARE weekdays INTEGER;
BEGIN
SELECT COUNT(extract(ISODOW FROM series)) INTO weekdays
FROM generate_series(date1::date, date2::date, '1 day'::interval) series
WHERE extract(ISODOW FROM series) < 6;
RETURN weekdays;
END;
$$ LANGUAGE plpgsql;