सप्ताहांत को छोड़कर दो तिथियों के बीच दिनों का COUNT चुनें


9

मैं सप्ताहांत को छोड़कर, दो अलग-अलग तिथियों के बीच दिनों की संख्या प्राप्त करने की कोशिश कर रहा हूं।

मुझे नहीं पता कि इस परिणाम को कैसे हासिल किया जाए।


1
कृपया संदर्भ के लिए अपनी तालिका संरचना पोस्ट करें। क्या अर्थ है SAT और SUN?
अब्दुल मनफ

जवाबों:


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() शामिल है , जब तक कि एक पूर्ण अंतराल (तीसरा पैरामीटर) फिट बैठता है। ऊपरी सीमा को केवल तभी बाहर रखा जाता है जब अंतिम अंतराल को काट दिया जाएगा, जो पूरे दिनों के मामले में नहीं है।

  • साथ पैटर्न ISODOWनिकालने () के लिए , रविवार के रूप में रिपोर्ट कर रहे हैं 7आईएसओ मानक के अनुसार,। एक सरल 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. चुने हुए दिनांक जनरेट_सरीज का उपयोग करते समय समावेशी होते हैं। इसलिए यदि आप बीच में दिन चाहते हैं तो प्रत्येक तिथि में 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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.