Hafta sonları hariç iki tarih arasında COUNT gün seçin


9

Hafta sonları hariç, iki farklı tarih arasındaki gün sayısını almaya çalışıyorum.

Bu sonuca nasıl ulaşacağımı bilmiyorum.


1
Lütfen referans için tablo yapınızı gönderin. Haftalar SAT ve SUN anlamına mı geliyor?
Abdul Manaf

Yanıtlar:


10

"Hafta sonu" ile Cumartesi ve Pazar demek istediğinizi varsayarsak , bu daha da basit olabilir:

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;
  • İçin ek bir alt sorgu seviyesine ihtiyacınız yok generate_series(). "Tablo işlevleri" olarak da adlandırılan SRF (küme dönen işlevleri), FROMyan tümcedeki tablolar gibi kullanılabilir .

  • Özellikle, tam bir aralığa (3. parametre) uyduğu sürece, çıkıştaki üst sınırı generate_series() içeren not edin . Üst sınır yalnızca son aralık kesilecekse hariç tutulur; bu, tam günlerde geçerli değildir.

  • EXTRACT () deseniISODOW ile pazar günleri 7ISO standardına göre bildirilir . Daha basit bir WHEREkoşul sağlar.

  • Aksine çağrı generate_series()ile timestampgiriş. İşte nedeni:

  • count(*)bu durumda biraz daha kısa ve hızlıdır count(the_day).

Alt ve / veya üst sınırı hariç tutmak için , buna göre 1 gün ekleyin / çıkarın. Genellikle, alt sınırı ekleyebilir ve üst sınırı hariç tutabilirsiniz:

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

Bu örnek 2013-12-15 ve 2014-01-02 arasındaki tüm tarihleri ​​(dahil) numaralandırmaktadır. İkinci sütun haftanın gününü verir (sayısal olarak 0 ile 6 arasında). Üçüncü sütun, haftanın gününün Cumartesi / Pazar olup olmadığını belirtir (bir hafta sonu olduğunu düşündüğünüz şeyi uyarlamanız gerekir) ve hafta içi günleri saymak için kullanılabilecek olan şeydir.

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

Bir haftasonunun Cumartesi ve Pazar olduğunu varsayarsak, aşağıdaki SQL'i kullanabilirsiniz.

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)

Tarihleri ​​seçeneklerinizle ((0,6) ise hariç tutmak istediğiniz haftanın günleriyle değiştirin.

Dikkat etmeniz gereken birkaç şey: -

  1. Hangi PostgreSQL sürümünü kullandığınızdan bahsetmediniz. Bu 9.1+ sürümünde çalışır ancak daha düşük sürümlerde de çalışması gerekir.

  2. Seçili tarihler create_series kullanılırken kapsayıcıdır. Aradaki günleri istiyorsanız, her tarihe 1 gün ekleyin.


0

Bunu kolaylaştırmak için yapabileceğiniz birkaç şey var. Kullanacağım yöntem bir tarih tablosunun mevcut olduğundan emin olmak olacaktır. Hızlı bir şekilde aşağıdakini oluşturabilirsiniz:

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

Tablo oluşturulduktan sonra, tabloyu tarih verileriyle nispeten hızlı bir şekilde doldurabilmeniz gerekir.

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

Daha sonra sorgunuzu bu tablodan hızlı bir kayıt sayısı olarak yazabilirsiniz.

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

0

İstediğiniz zaman kullanmak için bir işlev oluşturmanızı ve daha az yazmanızı öneririm; )

Yukarıdaki bu kod, hafta sonu günlerinin sayısını (Sat, Sun) sayan ve döndüren bir sql işlevi oluşturur. Tam da bu işlevi kullanma esnekliğiniz olacaktır.

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;

Bundan sonra, işlevi yalnızca aralıklı olarak hafta sonu günlerinin sayısını döndürmek için kullanabilirsiniz . Kullanılacak örnek:

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

Bu seçim dördü geri getirmeli çünkü birinci ve ikinci gün Pazartesi ve aralarında 2 Cumartesi ve 2 Pazar var.

Şimdi, yalnızca iş günlerini (hafta sonları olmadan) istediğiniz gibi döndürmek için , aşağıdaki örnek gibi bir çıkarma yapın:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.