选择两个日期之间的COUNT天(周末除外)


Answers:


10

假设“周末”是指周六周日,则可以更简单:

SELECT count(*) AS count_days_no_weekend
FROM   generate_series(timestamp '2014-01-01'
                     , timestamp '2014-01-10'
                     , interval  '1 day') the_day
WHERE  extract('ISODOW' FROM the_day) < 6;
  • 您不需要额外的子查询级别generate_series()。SRF(集合返回函数),也称为“表函数”,可以像该FROM子句中的表一样使用。

  • 特别要注意的是,只要适合整个间隔(第3个参数),它就会在输出中generate_series() 包括上限。仅当最后间隔被截断时才排除上限,整天情况并非如此。

  • 图案ISODOW对EXTRACT() ,周日报告为7,根据ISO标准。允许更简单的WHERE条件。

  • 而是generate_series()使用timestamp输入进行调用。原因如下:

  • count(*)count(the_day)在这种情况下,比稍短和快。

排除下限和/或上限,请相应地加减1天。通常,您可以包括下限,而排除上限:

SELECT count(*) AS count_days_no_weekend
FROM   generate_series(timestamp '2014-01-01'
                     , timestamp '2014-01-10' - interval '1 day'
                     , interval '1 day') the_day
WHERE  extract('ISODOW' FROM the_day) < 6;

3

此示例枚举了2013年12月15日至2014年1月2日之间的所有日期。第二列给出星期几(0到6之间的数字)。第三列标记一周中的某天是否为星期六/星期日(您必须调整您认为的周末是什么),并且可以用来计算工作日。

select '2013-12-15'::date + i * interval '1 day',
       extract('dow' from '2013-12-15'::date + i * interval '1 day') as dow,
       case when extract('dow' from '2013-12-15'::date + i * interval '1 day') in (0, 6)
               then false
            else true end as is_weekday
from generate_series(0, '2014-01-02'::date - '2013-12-15'::date) i
;

3

假设周末是星期六和星期日,则可以使用以下SQL。

select count(the_day) from 
    (select generate_series('2014-01-01'::date, '2014-01-10'::date, '1 day') as the_day) days
where extract('dow' from the_day) not in (0,6)

将日期替换为您的选择,将(0,6)替换为要排除的星期几。

您需要注意的几件事:

  1. 您没有提到您正在运行的PostgreSQL版本。这适用于9.1+,但应适用于较低版本。

  2. 使用generate_series时,所选日期包括在内。因此,如果您希望介于两者之间,请在每个日期前增加1天。


0

您可以通过以下几项操作来简化此操作。我将使用的方法是确保日期表可用。您可以像这样快速创建一个:

CREATE TABLE [dbo].[Dates]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY(0,1),
[Date] Date NOT NULL unique,
isWeekend BIT NOT NULL DEFAULT(0)
)

创建表格后,您应该可以相对快速地用日期数据填充表格。

set datefirst 6 --start date is saturday
INSERT INTO dbo.Dates(Date, isWeekend)
select 
    Date,
    case datepart(weekday,date) 
        --relies on DateFirst being set to 6
        when 2 then 1 
        when 1 then 1
        else 0
    end as isWeekend
from (
    select 
        dateadd(day, number - 1, 0) as date
    from (
        SELECT top 100000 row_number() over (order by o.object_id) as number
        FROM sys.objects o
            cross join sys.objects b
            cross join sys.objects c
    )numbers
)data

然后,您可以将查询作为该表中记录的快速计数来编写。

select count(*) as NumberOfWeekDays
from dbo.dates 
where isWeekend = 0
and date between '1 Jan 2013' and '31 Dec 2013'

0

我建议您创建一个函数,以便在需要时使用,减少编写工作;)

上面的代码将创建一个sql函数,该函数计算并返回周末(周六,周日)的天数。这样您就可以更加灵活地使用此功能。

CREATE OR REPLACE FUNCTION <YourSchemaNameOptional>.count_full_weekend_days(date, date)
RETURNS bigint AS
$BODY$
        select  COUNT(MySerie.*) as Qtde
        from    (select  CURRENT_DATE + i as Date, EXTRACT(DOW FROM CURRENT_DATE + i) as DiaDate
                 from    generate_series(date ($1) - CURRENT_DATE,  date ($2) - CURRENT_DATE ) i) as MySerie
        WHERE   MySerie.DiaDate in (6,0);
$BODY$
LANGUAGE 'SQL' IMMUTABLE STRICT;

之后,您可以使用该函数仅返回一个间隔中的周末天数。这是要使用的示例:

SELECT <YourSchemaNameOptional>.count_full_weekend_days('2017-09-11', '2017-09-25') as days; --> RES: 4

此选择必须返回四个,因为第一天和第二天是星期一,并且我们之间有2个星期六和2个星期日。

现在,只返回工作日(不含周末),只要你想,只是做一个减法,如下面的例子:

SELECT (date '2017-09-25' - date '2017-09-11' ) - <YourSchemaName>.count_full_weekend_days('2017-09-11', '2017-09-25'); --> RES: 14 - 4 = 10

-2
-- Returns number of weekdays between two dates
SELECT count(*)  as "numbers of days 
FROM generate_series(0, (‘from_date’::date - 'todate'::date)) i 
WHERE date_part('dow', 'todate'::date + i) NOT IN (0,6)


-- Returns number of weekdays between two dates
SELECT count(*)  as days 
FROM generate_series(0, ('2014/04/30'::date - '2014/04/01'::date)) i 
WHERE date_part('dow', '2014/04/01'::date + i) NOT IN (0,6)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.