Виберіть COUNT днів між двома датами, крім вихідних


9

Я намагаюся визначити кількість днів між двома різними датами, крім вихідних.

Я не знаю, як досягти цього результату.


1
Будь ласка, опублікуйте структуру таблиці для довідки. Вихідні означає SAT та SUN?
Абдул Манаф

Відповіді:


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пункті.

  • Зокрема, зверніть увагу на те, що generate_series() включає верхню межу у висновку, якщо відповідає повний інтервал (3-й параметр). Верхня межа виключається лише в тому випадку, якщо останній інтервал буде урізаний, що не стосується повних днів.

  • З малюнком ISODOWдля ЕКСТРАКТУ () , неділя , як повідомляється 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-01-02 (включно). У другому стовпці подано день тижня (числово, від 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. Вибрані дати включаються при використанні файлу Generator_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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.