Wählen Sie die Anzahl der Tage zwischen zwei Daten außer am Wochenende


9

Ich versuche, die Anzahl der Tage zwischen zwei verschiedenen Daten außer den Wochenenden zu ermitteln.

Ich weiß nicht, wie ich dieses Ergebnis erzielen soll.


1
Bitte geben Sie Ihre Tabellenstruktur als Referenz an. Wochenenden bedeutet SAT und SUN?
Abdul Manaf

Antworten:


10

Angenommen, mit "Wochenende" meinen Sie Samstag und Sonntag , kann dies noch einfacher sein:

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;
  • Sie benötigen keine zusätzliche Unterabfrageebene für generate_series(). SRF (Set Returning Functions), auch als "Tabellenfunktionen" bezeichnet, kann genau wie Tabellen in der FROMKlausel verwendet werden.

  • Sie daher vor allem generate_series() enthält die obere Grenze in dem Ausgang, so lange wie ein Vollintervall (3. Parameter) passt. Die Obergrenze wird nur ausgeschlossen, wenn das letzte Intervall abgeschnitten würde, was bei vollen Tagen nicht der Fall ist.

  • Mit dem Muster ISODOWfür EXTRACT () werden Sonntage 7gemäß dem ISO-Standard gemeldet . Ermöglicht einen einfacheren WHEREZustand.

  • Rufen Sie lieber generate_series()mit timestampEingabe an. Hier ist warum:

  • count(*)ist etwas kürzer und schneller als count(the_day)in diesem Fall.

Um eine Unter- und / oder Obergrenze auszuschließen , addieren / subtrahieren Sie 1 Tag entsprechend. In der Regel können Sie die untere und die obere Grenze einschließen:

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

In diesem Beispiel werden alle Daten zwischen dem 15.12.2013 und dem 02.01.2014 (einschließlich) aufgelistet. Die zweite Spalte gibt den Wochentag an (numerisch zwischen 0 und 6). In der dritten Spalte wird angegeben, ob der Wochentag ein Samstag / Sonntag ist oder nicht (Sie müssen anpassen, was Sie als Wochenende betrachten) und was zum Zählen von Wochentagen verwendet werden kann.

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

Angenommen, ein Wochenende ist Samstag und Sonntag, können Sie die folgende SQL verwenden.

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)

Ersetzen Sie die Daten durch Ihre Auswahl und die (0,6) durch die Wochentage, die Sie ausschließen möchten.

Einige Dinge, die Sie beachten müssen: -

  1. Sie haben nicht erwähnt, welche Version von PostgreSQL Sie ausführen. Dies funktioniert unter 9.1+, sollte aber unter niedrigeren Versionen funktionieren.

  2. Die ausgewählten Daten sind bei Verwendung von generate_series inklusive. Wenn Sie also Tage dazwischen möchten, fügen Sie jedem Datum 1 Tag hinzu.


0

Es gibt einige Dinge, die Sie tun können, um dies zu vereinfachen. Die Methode, die ich verwenden würde, wäre sicherzustellen, dass eine Tabelle mit Daten verfügbar ist. Sie können schnell eine erstellen, wie folgt:

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

Sobald die Tabelle erstellt wurde, sollten Sie sie relativ schnell mit Datumsdaten füllen können.

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

Sie können Ihre Abfrage dann als schnelle Anzahl von Datensätzen aus dieser Tabelle schreiben.

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

0

Ich empfehle Ihnen, eine Funktion zu erstellen, die Sie verwenden können, wann immer Sie möchten, und weniger zu schreiben. )

Dieser obige Code erstellt eine SQL-Funktion, die die Anzahl der Wochenendtage (Sa, So) zählt und zurückgibt. So wie Sie diese Funktion flexibler nutzen können.

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;

Danach können Sie mit der Funktion nur die Anzahl der Wochenendtage in einem Intervall zurückgeben. Hier ist das zu verwendende Beispiel:

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

Diese Auswahl muss vier zurückgeben, da der erste und der zweite Tag Montag sind und wir zwei Samstage und zwei Sonntage dazwischen haben.

Nun, nur für die Rückkehr Werktagen (ohne Wochenende), wie Sie wollen , nur eine Subtraktion machen, wie im folgenden Beispiel:

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.