Pilih COUNT hari antara dua tanggal kecuali akhir pekan

9

Saya mencoba mendapatkan jumlah hari antara dua tanggal yang berbeda, kecuali akhir pekan.

Saya tidak tahu bagaimana mencapai hasil ini.

pragati basa
sumber
1
Silakan posting struktur tabel Anda untuk referensi. Akhir pekan berarti SAT dan SUN?
Abdul Manaf

Jawaban:

10

Dengan asumsi bahwa dengan "akhir pekan" yang Anda maksud adalah hari Sabtu dan Minggu , ini bisa menjadi lebih sederhana:

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;
  • Anda tidak perlu level subquery tambahan untuk generate_series(). SRF (atur fungsi pengembalian), juga disebut sebagai "fungsi tabel", dapat digunakan seperti tabel dalam FROMklausa.

  • Perhatikan khususnya yang generate_series() menyertakan batas atas dalam output, selama interval penuh (parameter ke-3) cocok. Batas atas hanya dikecualikan jika interval terakhir akan terpotong, yang tidak demikian halnya dengan hari penuh.

  • Dengan pola ISODOWuntuk EXTRACT () , hari Minggu dilaporkan sebagai 7, sesuai dengan standar ISO. Memungkinkan untuk WHEREkondisi yang lebih sederhana .

  • Lebih baik panggil generate_series()dengan timestampinput. Inilah alasannya:

  • count(*)sedikit lebih pendek dan lebih cepat daripada count(the_day), melakukan hal yang sama dalam hal ini.

Untuk mengecualikan batas bawah dan / atau atas, tambahkan / kurangi sesuai 1 hari. Biasanya, Anda dapat menyertakan yang lebih rendah dan mengecualikan batas atas:

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;
Erwin Brandstetter
sumber
3

Contoh ini menyebutkan semua tanggal antara 2013-12-15 dan 2014-01-02 (inklusif). Kolom kedua memberikan hari dalam seminggu (secara numerik, antara 0 dan 6). Kolom ketiga menandai apakah hari dalam seminggu adalah hari Sabtu / Minggu atau tidak (Anda harus menyesuaikan apa yang Anda anggap sebagai akhir pekan) dan apa yang dapat digunakan untuk menghitung hari kerja.

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
;
menghasilkan kepalsuan
sumber
3

Dengan asumsi bahwa akhir pekan adalah hari Sabtu dan Minggu, Anda dapat menggunakan SQL berikut.

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)

Ganti tanggal dengan pilihan Anda dan (0,6) dengan hari-hari dalam minggu yang ingin Anda kecualikan.

Beberapa hal yang perlu Anda perhatikan: -

  1. Anda belum menyebutkan versi PostgreSQL apa yang Anda jalankan. Ini berfungsi pada 9.1+ tetapi harus bekerja pada versi yang lebih rendah.

  2. Tanggal yang dipilih inklusif saat menggunakan generate_series. Jadi, jika Anda ingin berhari-hari, tambahkan 1 hari untuk setiap tanggal.

Imraan
sumber
0

Ada beberapa hal yang dapat Anda lakukan untuk mempermudah ini. Metode yang akan saya gunakan adalah memastikan bahwa daftar tanggal tersedia. Anda dapat dengan cepat membuat yang seperti ini:

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

Setelah tabel dibuat, Anda harus dapat mengisinya dengan data tanggal yang relatif cepat.

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

Anda kemudian dapat menulis kueri Anda sebagai penghitungan cepat catatan dari tabel ini.

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

Saya menyarankan Anda untuk membuat fungsi untuk digunakan kapan pun Anda mau dan menulis lebih sedikit; )

Kode di atas akan membuat fungsi sql yang menghitung dan mengembalikan jumlah hari akhir pekan (Sabtu, Minggu). Hanya dengan cara ini Anda akan memiliki lebih banyak fleksibilitas untuk menggunakan fungsi ini.

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;

Setelah itu, Anda dapat menggunakan fungsi ini untuk mengembalikan hanya jumlah hari akhir pekan dalam interval. Inilah contoh untuk digunakan:

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

Pilih ini harus mengembalikan empat karena hari pertama dan kedua adalah Senin, dan kami memiliki 2 Sabtu dan 2 Minggu di antara mereka.

Sekarang, untuk mengembalikan hanya hari kerja (tanpa akhir pekan), seperti yang Anda inginkan , cukup kurangi, seperti contoh di bawah ini:

SELECT (date '2017-09-25' - date '2017-09-11' ) - <YourSchemaName>.count_full_weekend_days('2017-09-11', '2017-09-25'); --> RES: 14 - 4 = 10
Wagner Cipriano
sumber
-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)
Aman_Kumar
sumber