Seleziona COUNT giorni tra due date tranne i fine settimana


9

Sto cercando di ottenere il numero di giorni tra due date diverse, tranne i fine settimana.

Non so come raggiungere questo risultato.


1
Si prega di pubblicare la struttura della tabella come riferimento. Week-end significa SAT e SUN?
Abdul Manaf,

Risposte:


10

Supponendo che per "fine settimana" intendi sabato e domenica , questo può essere ancora più semplice:

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;
  • Non è necessario un livello di subquery aggiuntivo per generate_series(). SRF (imposta funzioni di ritorno), noto anche come "funzioni di tabella", può essere utilizzato proprio come le tabelle nella FROMclausola.

  • Si noti in particolare che generate_series() include il limite superiore nell'output, purché si adatti un intervallo completo (3 ° parametro). Il limite superiore viene escluso solo se l'ultimo intervallo viene troncato, il che non è il caso dei giorni interi.

  • Con lo schema ISODOWper EXTRACT () , le domeniche vengono segnalate come 7, secondo lo standard ISO. Permette una WHEREcondizione più semplice .

  • Piuttosto chiama generate_series()con timestampinput. Ecco perché:

  • count(*)è leggermente più corto e più veloce di count(the_day), facendo lo stesso in questo caso.

Per escludere il limite inferiore e / o superiore, aggiungere / sottrarre 1 giorno di conseguenza. In genere, è possibile includere il limite inferiore ed escludere il limite superiore:

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

Questo esempio elenca tutte le date tra il 15-12-2013 e il 2014-01-02 (inclusivamente). La seconda colonna indica il giorno della settimana (numericamente, tra 0 e 6). La terza colonna indica se il giorno della settimana è un sabato / domenica o meno (dovrai adattare ciò che consideri un fine settimana) ed è ciò che potrebbe essere usato per contare i giorni della settimana.

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

Supponendo che un fine settimana sia sabato e domenica, è possibile utilizzare il seguente 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)

Sostituisci le date con le tue scelte e (0,6) con i giorni della settimana che desideri escludere.

Alcune cose che devi prendere in considerazione: -

  1. Non hai menzionato la versione di PostgreSQL in esecuzione. Funziona su 9.1+ ma dovrebbe funzionare su versioni inferiori.

  2. Le date scelte sono incluse quando si utilizza generate_serie. Quindi, se vuoi giorni tra, aggiungi 1 giorno a ciascuna data.


0

Ci sono un paio di cose che puoi fare per renderlo più semplice. Il metodo che utilizzerei sarebbe quello di assicurarmi che sia disponibile una tabella di date. Puoi crearne rapidamente uno in questo modo:

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

Una volta creata la tabella, dovresti essere in grado di popolarla con i dati della data in modo relativamente rapido.

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

È quindi possibile scrivere la query come conteggio rapido dei record da questa tabella.

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

0

Ti consiglio di creare una funzione da usare ogni volta che vuoi e scrivere di meno; )

Questo codice sopra creerà una funzione sql che conta e restituisce la quantità di giorni del fine settimana (sabato, domenica). Proprio come avrai più flessibilità per usare questa funzione.

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;

Successivamente, è possibile utilizzare la funzione per restituire solo il numero di giorni del fine settimana in un intervallo. Ecco l'esempio da usare:

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

Questa selezione deve restituire quattro perché il primo e il secondo giorno sono lunedì e tra loro abbiamo 2 sabati e 2 domeniche.

Ora, per restituire solo giorni lavorativi (senza fine settimana), come vuoi , fai una sottrazione, come nell'esempio seguente:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.