web-dev-qa-db-fra.com

Sélectionnez COUNT jours entre deux dates sauf le week-end

J'essaie d'obtenir le nombre de jours entre deux dates différentes, sauf les week-ends.

Je ne sais pas comment obtenir ce résultat.

9
pragati basa

En supposant que par "week-end" vous voulez dire samedi et dimanche, cela peut être encore plus simple:

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;
  • Vous n'avez pas besoin d'un niveau de sous-requête supplémentaire pour generate_series() . SRF (set return functions), également appelé "table-fonctions", peut être utilisé comme les tables de la clause FROM.

  • Notez en particulier que generate_series() inclut la limite supérieure dans la sortie, tant qu'un complet = intervalle (3e paramètre) correspond. La limite supérieure n'est exclue que si le dernier intervalle est tronqué, ce qui n'est pas le cas pour les jours entiers.

  • Avec le modèle ISODOW pour EXTRACT () , les dimanches sont signalés comme 7, Selon la norme ISO. Permet une condition WHERE plus simple.

  • Appelez plutôt generate_series() avec timestamp entrée. Voici pourquoi:

  • count(*) est légèrement plus court et plus rapide que count(the_day), faisant de même dans ce cas.

Pour exclure borne inférieure et/ou supérieure, ajoutez/soustrayez 1 jour en conséquence. En règle générale, vous pouvez inclure la limite inférieure et exclure la limite supérieure:

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;
10
Erwin Brandstetter

Cet exemple énumère toutes les dates entre le 2013-12-15 et le 2014-01-02 (inclusivement). La deuxième colonne donne le jour de la semaine (numériquement, entre 0 et 6). La troisième colonne indique si le jour de la semaine est un samedi/dimanche ou non (vous devrez adapter ce que vous considérez comme un week-end) et c'est ce qui pourrait être utilisé pour compter les jours de la semaine.

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
yieldsfalsehood

En supposant qu'un week-end est le samedi et le dimanche, vous pouvez utiliser le SQL suivant.

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)

Remplacez les dates par vos choix et le (0,6) par les jours de la semaine que vous souhaitez exclure.

Quelques points dont vous devez prendre note: -

  1. Vous n'avez pas mentionné la version de PostgreSQL que vous utilisez. Cela fonctionne sur 9.1+ mais devrait fonctionner sur les versions inférieures.

  2. Les dates choisies sont incluses lors de l'utilisation de generate_series. Donc, si vous voulez des jours entre les deux, ajoutez 1 jour à chaque date.

3
Imraan

Il y a deux ou trois choses que vous pouvez faire pour rendre cela plus facile. La méthode que j'utiliserais serait de s'assurer qu'un tableau des dates est disponible. Vous pouvez rapidement en créer un comme ceci:

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

Une fois le tableau créé, vous devriez pouvoir le remplir avec des données de date relativement rapidement.

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

Vous pouvez ensuite écrire votre requête sous la forme d'un décompte rapide des enregistrements de cette table.

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

Je vous suggère de créer une fonction à utiliser quand vous le souhaitez et d'écrire moins; )

Ce code ci-dessus créera une fonction sql qui compte et renvoie le nombre de jours de week-end (samedi, dimanche). Tout comme vous aurez plus de flexibilité pour utiliser cette fonction.

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;

Après cela, vous pouvez utiliser la fonction pour renvoyer uniquement le nombre de jours de week-end dans un intervalle. Voici l'exemple à utiliser:

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

Cette sélection doit renvoyer quatre car le premier et le deuxième jour sont lundi, et nous avons 2 samedis et 2 dimanches entre eux.

Maintenant, pour ne renvoyer que les jours ouvrables (sans week-end), comme vous le souhaitez , faites simplement une soustraction, comme dans l'exemple ci-dessous :

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