เลือก COUNT วันระหว่างสองวันยกเว้นวันหยุดสุดสัปดาห์


9

ฉันพยายามรับจำนวนวันระหว่างสองวันที่แตกต่างกันยกเว้นวันหยุดสุดสัปดาห์

ฉันไม่รู้ว่าจะบรรลุผลนี้ได้อย่างไร


1
กรุณาโพสต์โครงสร้างตารางของคุณสำหรับการอ้างอิงสัปดาห์หมายถึง SAT และอาทิตย์?
Abdul Manaf

คำตอบ:


10

สมมติว่า "วันหยุดสุดสัปดาห์" คุณหมายถึงวันเสาร์และวันอาทิตย์สิ่งนี้อาจง่ายกว่านี้:

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;
  • คุณไม่ต้องการระดับการสืบค้นย่อยเพิ่มเติมgenerate_series()อีก SRF (ตั้งค่าฟังก์ชั่นการคืน) หรือที่เรียกว่า "ฟังก์ชั่นตาราง" สามารถใช้งานได้เช่นเดียวกับตารางในส่วนFROMคำสั่ง

  • หมายเหตุโดยเฉพาะอย่างยิ่งที่generate_series() รวมถึงขอบเขตบนในผลลัพธ์ตราบใดที่ช่วงเวลาเต็ม (พารามิเตอร์ที่ 3) เหมาะ ขอบเขตบนจะไม่รวมหากช่วงเวลาสุดท้ายจะถูกตัดทอนซึ่งไม่ใช่กรณีที่มีวันเต็ม

  • ด้วยรูปแบบISODOWสำหรับ EXTRACT ()วันอาทิตย์จะถูกรายงาน7ตามมาตรฐาน ISO ช่วยให้WHEREสภาพง่ายขึ้น

  • ค่อนข้างโทรgenerate_series()ด้วยtimestampอินพุต นี่คือเหตุผล:

  • count(*)สั้นและเร็วกว่าเล็กน้อยcount(the_day)ทำแบบเดียวกันในกรณีนี้

หากต้องการแยกส่วนล่างและ / หรือขอบบนให้เพิ่ม / ลบ 1 วันตามลำดับ โดยทั่วไปคุณอาจรวมส่วนล่างและแยกขอบเขตบน:

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

ตัวอย่างนี้ระบุวันที่ทั้งหมดระหว่าง 2013-12-15 และ 2014-01-02 (รวม) คอลัมน์ที่สองให้วันของสัปดาห์ (ตัวเลขระหว่าง 0 ถึง 6) คอลัมน์ที่สามทำเครื่องหมายว่าวันในสัปดาห์เป็นวันเสาร์ / วันอาทิตย์หรือไม่ (คุณจะต้องปรับเปลี่ยนสิ่งที่คุณพิจารณาว่าเป็นวันหยุดสุดสัปดาห์) และเป็นสิ่งที่สามารถใช้ในการนับวันทำงานได้

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

สมมติว่าวันหยุดสุดสัปดาห์เป็นวันเสาร์และวันอาทิตย์คุณสามารถใช้ SQL ต่อไปนี้

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)

แทนที่วันที่ด้วยตัวเลือกของคุณและ (0,6) ด้วยวันในสัปดาห์ที่คุณต้องการยกเว้น

บางสิ่งที่คุณต้องทราบ: -

  1. คุณยังไม่ได้กล่าวถึงรุ่นของ PostgreSQL ที่คุณใช้งานอยู่ ใช้งานได้กับ 9.1+ แต่ควรใช้กับเวอร์ชั่นต่ำ

  2. วันที่ที่เลือกจะถูกรวมเมื่อใช้ generate_series ดังนั้นหากคุณต้องการวันในระหว่างนั้นเพิ่ม 1 วันในแต่ละวัน


0

มีสองสิ่งที่คุณสามารถทำได้เพื่อทำให้ง่ายขึ้น วิธีที่ฉันจะใช้คือเพื่อให้แน่ใจว่ามีตารางวันที่ให้บริการ คุณสามารถสร้างสิ่งที่ชอบได้อย่างรวดเร็ว:

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

เมื่อสร้างตารางแล้วคุณควรจะสามารถเติมข้อมูลด้วยข้อมูลวันที่ได้อย่างรวดเร็ว

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

จากนั้นคุณสามารถเขียนคิวรีของคุณเป็นจำนวนระเบียนที่รวดเร็วจากตารางนี้

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

0

ฉันแนะนำให้คุณสร้างฟังก์ชั่นการใช้งานทุกครั้งที่คุณต้องการและเขียนน้อยลง )

รหัสข้างต้นนี้จะสร้างฟังก์ชั่น sql ที่นับและคืนจำนวนวันหยุดสุดสัปดาห์ (วันเสาร์อาทิตย์) เพียงแค่คุณมีความยืดหยุ่นในการใช้ฟังก์ชั่นนี้มากขึ้น

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;

หลังจากนั้นคุณสามารถใช้ฟังก์ชั่นเพื่อกลับเฉพาะจำนวนวันหยุดสุดสัปดาห์ในช่วงเวลา นี่คือตัวอย่างการใช้งาน:

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

ตัวเลือกนี้ต้องส่งคืนสี่รายการเนื่องจากวันแรกและวันที่สองคือวันจันทร์และเรามีวันเสาร์ 2 วันและวันอาทิตย์ 2 วันระหว่างวันเหล่านั้น

ตอนนี้หากต้องการคืนเฉพาะวันทำการ (โดยไม่มีวันหยุดสุดสัปดาห์) ตามที่คุณต้องการเพียงทำการลบอย่างเช่นตัวอย่างด้านล่าง:

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.