Saya mencoba mendapatkan jumlah hari antara dua tanggal yang berbeda, kecuali akhir pekan.
Saya tidak tahu bagaimana mencapai hasil ini.
Saya mencoba mendapatkan jumlah hari antara dua tanggal yang berbeda, kecuali akhir pekan.
Saya tidak tahu bagaimana mencapai hasil ini.
Jawaban:
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 FROM
klausa.
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 ISODOW
untuk EXTRACT () , hari Minggu dilaporkan sebagai 7
, sesuai dengan standar ISO. Memungkinkan untuk WHERE
kondisi yang lebih sederhana .
Lebih baik panggil generate_series()
dengan timestamp
input. 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;
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
;
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: -
Anda belum menyebutkan versi PostgreSQL apa yang Anda jalankan. Ini berfungsi pada 9.1+ tetapi harus bekerja pada versi yang lebih rendah.
Tanggal yang dipilih inklusif saat menggunakan generate_series. Jadi, jika Anda ingin berhari-hari, tambahkan 1 hari untuk setiap tanggal.
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'
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
-- 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)