SQL Server में सप्ताह का पहला दिन प्राप्त करें


97

मैं सप्ताह के पहले दिन के रूप में एकत्रित तिथि को संग्रहीत करके सप्ताह के समूह रिकॉर्ड की कोशिश कर रहा हूं। हालाँकि, मैं जिस मानक तकनीक का उपयोग तिथियों को राउंड करने के लिए करता हूं, वह हफ़्तों के साथ सही तरीके से काम करने के लिए प्रकट नहीं होती है (हालांकि यह दिनों, महीनों, वर्षों, तिमाहियों और मेरे द्वारा इसे लागू किए गए किसी भी अन्य समय-सीमा) के लिए है।

यहाँ एसक्यूएल है:

select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), 0);

यह रिटर्न 2011-08-22 00:00:00.000, जो सोमवार है, रविवार नहीं। @@datefirstरिटर्न का चयन 7, जो रविवार के लिए कोड है, इसलिए जहां तक ​​मुझे पता है, सर्वर सही ढंग से सेटअप है।

मैं उपरोक्त कोड को बदलकर इसे आसानी से बायपास कर सकता हूं:

select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), -1);

लेकिन इस तथ्य से कि मुझे इस तरह का अपवाद करना पड़ता है, इससे मुझे थोड़ी बेचैनी होती है। साथ ही, अगर यह एक डुप्लिकेट प्रश्न है, तो क्षमा करें। मुझे कुछ संबंधित प्रश्न मिले लेकिन किसी ने भी इस पहलू को विशेष रूप से संबोधित नहीं किया।


9
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7@@datefirstमुझे लगता है कि स्थापित करने के लिए लगातार परवाह किए बिना । सोमवार = 2. के साथ
मार्टिन स्मिथ

जवाबों:


149

उत्तर देने के लिए कि आपको सोमवार क्यों है और रविवार नहीं है:

आप दिनांक 0 पर कई सप्ताह जोड़ रहे हैं। दिनांक 0 क्या है? 1900/01/01। 1900-01-01 को क्या दिन था? सोमवार। तो आपके कोड में आप कह रहे हैं, 1 जनवरी 1900 से लेकर सोमवार तक कितने सप्ताह बीत चुके हैं? चलो कि [n] कहते हैं। ठीक है, अब सोमवार, 1 जनवरी, 1900 को [n] सप्ताह जोड़ें। आपको आश्चर्य नहीं होना चाहिए कि यह एक सोमवार होने के नाते समाप्त होता है। DATEADDऐसा कोई विचार नहीं है कि आप सप्ताह जोड़ना चाहते हैं, लेकिन केवल जब तक आप रविवार तक नहीं जाते हैं, यह सिर्फ 7 दिन जोड़ रहा है, तो 7 और दिन जोड़ रहा है, ... जैसे कि DATEDIFFकेवल उन सीमाओं को पहचानता है जिन्हें पार किया गया है। उदाहरण के लिए, ये दोनों 1 लौटते हैं, भले ही कुछ लोग शिकायत करते हैं कि ऊपर या नीचे गोल करने के लिए निर्मित कुछ समझदार तर्क होना चाहिए:

SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');

रविवार कैसे प्राप्त करें, इसका उत्तर देने के लिए:

यदि आप रविवार चाहते हैं, तो एक आधार तिथि चुनें जो सोमवार नहीं, बल्कि रविवार है। उदाहरण के लिए:

DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);

यदि आप अपनी DATEFIRSTसेटिंग बदलते हैं (या एक अलग सेटिंग वाले उपयोगकर्ता के लिए आपका कोड चल रहा है) तो यह नहीं टूटेगा - बशर्ते कि आप अभी भी वर्तमान सेटिंग की परवाह किए बिना एक रविवार चाहते हों। यदि आप चाहते हैं कि वे दो उत्तर दें, तो आपको एक फ़ंक्शन का उपयोग करना चाहिए , जो सेटिंग पर निर्भर करता हैDATEFIRST , जैसे

SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);

इसलिए यदि आप अपनी DATEFIRSTसेटिंग सोमवार, मंगलवार को बदलते हैं, तो आपके पास क्या है, व्यवहार बदल जाएगा। आप कौन सा व्यवहार चाहते हैं, इसके आधार पर, आप इनमें से किसी एक कार्य का उपयोग कर सकते हैं:

CREATE FUNCTION dbo.StartOfWeek1 -- always a Sunday
(
    @d DATE
)
RETURNS DATE
AS
BEGIN
    RETURN (SELECT DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @d), '19050101'));
END
GO

... या ...

CREATE FUNCTION dbo.StartOfWeek2 -- always the DATEFIRST weekday
(
    @d DATE
)
RETURNS DATE
AS
BEGIN
    RETURN (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, @d), @d));
END
GO

अब, आपके पास बहुत सारे विकल्प हैं, लेकिन कौन सा सबसे अच्छा प्रदर्शन करता है? मुझे आश्चर्य होगा अगर कोई बड़ा अंतर होगा लेकिन मैंने अब तक प्रदान किए गए सभी उत्तरों को एकत्र किया और उन्हें परीक्षणों के दो सेटों के माध्यम से चलाया - एक सस्ता और एक महंगा। मैंने क्लाइंट आँकड़ों को मापा क्योंकि मैं I / O या मेमोरी को यहाँ प्रदर्शन में हिस्सा नहीं देखता (हालाँकि वे फ़ंक्शन के उपयोग के आधार पर खेल में आ सकते हैं)। मेरे परीक्षणों में परिणाम हैं:

"सस्ता काम असाइनमेंट क्वेरी:

Function - client processing time / wait time on server replies / total exec time
Gandarez     - 330/2029/2359 - 0:23.6
me datefirst - 329/2123/2452 - 0:24.5
me Sunday    - 357/2158/2515 - 0:25.2
trailmax     - 364/2160/2524 - 0:25.2
Curt         - 424/2202/2626 - 0:26.3

"महंगी" असाइनमेंट क्वेरी:

Function - client processing time / wait time on server replies / total exec time
Curt         - 1003/134158/135054 - 2:15
Gandarez     -  957/142919/143876 - 2:24
me Sunday    -  932/166817/165885 - 2:47
me datefirst -  939/171698/172637 - 2:53
trailmax     -  958/173174/174132 - 2:54

मैं अपने परीक्षणों के विवरण को रिले कर सकता हूं यदि वांछित है - यहां रोकना क्योंकि यह पहले से ही काफी लंबा-घुमावदार हो रहा है। गणना की संख्या और इनलाइन कोड को देखते हुए, मैं कर्ट को सबसे तेज़ गति से बाहर आते देख थोड़ा हैरान था। हो सकता है कि मैं इसके बारे में कुछ और गहन परीक्षण और ब्लॉग चलाऊं ... अगर आप लोगों को मेरे कार्यों को कहीं और प्रकाशित करने में कोई आपत्ति नहीं है।


इसलिए, अगर मैं रविवार को शुरू होने और शनिवार को समाप्त होने के लिए अपने सप्ताह पर विचार करता हूं, तो मैं सप्ताह के अंतिम दिन को किसी भी तारीख को प्राप्त कर सकता हूं @ इस तरह: SELECT DATEADD (wk, DatedIFF (wk, '19041231', @d), '19041231')
बोडाद

21

इन्हें प्राप्त करने के लिए:

सोमवार = 1 और रविवार = 7:

SELECT 1 + ((5 + DATEPART(dw, GETDATE()) + @@DATEFIRST) % 7);

रविवार = 1 और शनिवार = 7:

SELECT 1 + ((6 + DATEPART(dw, GETDATE()) + @@DATEFIRST) % 7);

ऊपर एक समान उदाहरण था, लेकिन "% 7" को दोगुना करने के लिए यह बहुत धीमा होगा।


यह सप्ताह के प्रारंभ में सूर्य या सोम होने से दिन की संख्या प्राप्त करने के लिए बहुत अच्छा काम करता है। धन्यवाद
Fandango68

वैकल्पिक रूप से select (datediff(dd,5,cal.D_DATE)%7 + 1)औरselect (datediff(dd,6,cal.D_DATE)%7 + 1)
vasja

8

उन लोगों के लिए जिन्हें काम पर उत्तर की आवश्यकता है और फ़ंक्शन बनाने के लिए आपके डीबीए द्वारा मना किया गया है, निम्नलिखित समाधान काम करेंगे:

select *,
cast(DATEADD(day, -1*(DATEPART(WEEKDAY, YouDate)-1), YourDate) as DATE) as WeekStart
From.....

इससे उस सप्ताह की शुरुआत होती है। यहां मैं मानता हूं कि रविवार सप्ताह की शुरुआत है। अगर आपको लगता है कि सोमवार की शुरुआत है, तो आपको इसका उपयोग करना चाहिए:

select *,
cast(DATEADD(day, -1*(DATEPART(WEEKDAY, YouDate)-2), YourDate) as DATE) as WeekStart
From.....

5

यह मेरे लिए अद्भुत काम करता है:

निर्माण समारोह [dbo] [StartOfWeek]
(
  @INPUTDATE DATETIME
)
रिटर्न्स डैटटाइम

जैसा
शुरू
  - यह कार्य नहीं करता है।
  - DATEFIRST 1 सेट करें - सप्ताह के पहले दिन होने के लिए सोमवार सेट करें।

  DECLARE @DOW INT - सप्ताह के दिन को स्टोर करने के लिए
  SIN @INPUTDATE = CONVERT (VARCHAR (10), @INPUTDATE, 111)
  SET @DOW = DATEPART (DW, @INPUTDATE)

  - सोमवार को 1, सोमवार से 2 तक का जादू बदलना, आदि।
  - SQL सर्वर सप्ताह की शुरुआत के बारे में क्या सोचता है।
  - लेकिन यहां हमारे पास रविवार को 0 के रूप में चिह्नित किया गया है, लेकिन हम इसे बाद में ठीक कर देते हैं।
  SET @DOW = (@DOW + @@ DATEFIRST - 1)% =
  IF @DOW = 0 SET @DOW = 7 - रविवार के लिए ठीक करें

  RETURN DATEADD (DD, 1 - @ DOW, @ INPUTDATE)

समाप्त

ऐसा लगता है कि आज की तारीख में सोमवार को वापसी होगी, रविवार नहीं। ओपी के पास पहले से ही एक समारोह है जो सोमवार को लौटता है, वह चाहता है कि वह रविवार को लौट आए। :-)
एरोन बर्ट्रेंड

doh! मुझे अगली बार प्रश्नों को अधिक सावधानी से पढ़ना चाहिए। हालांकि, यदि आवश्यक हो, तो मेरे समाधान को आसानी से समायोजित किया जा सकता है। ओपी की तरह लगता है कि वैसे भी स्वीकार किए गए जवाब से खुश है -)
ट्रेलमैक्स

यह मेरी मशीन पर सही समाधान है, क्योंकि मेरे लिए: DATEADD (ww, DatedIFF (ww, 0, CONVERT (DATE, '2017-10-8')), 0) 2017-10-9 रिटर्न!
CMD

3

इस स्क्रिप्ट को बनाया गया:

create function dbo.F_START_OF_WEEK
(
    @DATE           datetime,
    -- Sun = 1, Mon = 2, Tue = 3, Wed = 4
    -- Thu = 5, Fri = 6, Sat = 7
    -- Default to Sunday
    @WEEK_START_DAY     int = 1 
)
/*
Find the fisrt date on or before @DATE that matches 
day of week of @WEEK_START_DAY.
*/
returns     datetime
as
begin
declare  @START_OF_WEEK_DATE    datetime
declare  @FIRST_BOW     datetime

-- Check for valid day of week
if @WEEK_START_DAY between 1 and 7
    begin
    -- Find first day on or after 1753/1/1 (-53690)
    -- matching day of week of @WEEK_START_DAY
    -- 1753/1/1 is earliest possible SQL Server date.
    select @FIRST_BOW = convert(datetime,-53690+((@WEEK_START_DAY+5)%7))
    -- Verify beginning of week not before 1753/1/1
    if @DATE >= @FIRST_BOW
        begin
        select @START_OF_WEEK_DATE = 
        dateadd(dd,(datediff(dd,@FIRST_BOW,@DATE)/7)*7,@FIRST_BOW)
        end
    end

return @START_OF_WEEK_DATE

end
go

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307


2

शायद आपको इसकी आवश्यकता है:

SELECT DATEADD(DD, 1 - DATEPART(DW, GETDATE()), GETDATE())

या

DECLARE @MYDATE DATETIME
SET @MYDATE = '2011-08-23'
SELECT DATEADD(DD, 1 - DATEPART(DW, @MYDATE), @MYDATE)

समारोह

CREATE FUNCTION [dbo].[GetFirstDayOfWeek]
( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN

SET @pInputDate = CONVERT(VARCHAR(10), @pInputDate, 111)
RETURN DATEADD(DD, 1 - DATEPART(DW, @pInputDate),
               @pInputDate)

END
GO

6
DATEPART(DWपर निर्भर है@@datefirst
मार्टिन स्मिथ

मुझे इसकी सरलता पसंद है। यह डेटा के बहुत बड़े सेट के लिए भी अच्छी तरह से चलता है।
क्विक जो स्मिथ

2
क्यों न केवल इनपुट पैरामीटर बनाया जाए, DATEतो आपको VARCHARकिसी भी आकस्मिक समय घटक को वापस करने के लिए कोई उप-इष्टतम रूपांतरण करने की ज़रूरत नहीं है और जो किसी भी आकस्मिक समय घटक में पारित हो गया है उसे वापस करने के लिए।
हारून बर्ट्रेंड

कनवर्ट किए गए फ़ंक्शन का उपयोग किया गया था क्योंकि लौटाया गया मान Timeमानों की आवश्यकता नहीं है।
गंदेरेज़

1
हां, लेकिन मुद्दा यह है कि एक varchar और वापस फिर से परिवर्तित करना महंगा है। यदि आपके पास बस एक DATE पैरामीटर है, तो आपको परवाह नहीं है कि क्या समय शामिल किया गया था ... यह आपके लिए छीन लिया जाता है।
हारून बर्ट्रेंड

2
सृजन समारोह dbo.fnFirstWorkingDayOfTheWeek
(
    @ समवर्ती तिथि
)
RETURNS INT
जैसा
शुरू
    - DATEFIRST सेटिंग प्राप्त करें
    DECLARE @ds int = @@ DATEFIRST 
    - वर्तमान DATEFIRST सेटिंग के अंतर्गत सप्ताह का दिन प्राप्त करें
    DECLARE @dow int = DATEPART (dw, @ currentDate) 

    DECLARE @wd int = 1 + ((((dow + @ ds)% 7) +5)% 7 - यह हमेशा Mon को 1, Tue को 2 ... Sun को 7 के रूप में लौटाता है। 

    RETURN DATEADD (dd, 1- @ wd, @ currentDate) 

समाप्त

यह एकमात्र कार्य है जिसने SQL Server 2005 में मेरे लिए काम किया। धन्यवाद
Fandango68

@ फर्नांडो 68 क्या आप बता सकते हैं कि अन्य समाधान कैसे नहीं चले ?
हारून बर्ट्रेंड

@AaronBertrand खेद याद नहीं है, लेकिन मुझे लगता है कि मैं एक त्वरित जवाब पर ध्यान केंद्रित कर रहा था और मैंने आपकी कोशिश की लेकिन किसी कारण से यह मेरे लिए काम नहीं किया।
Fandango68

@ फर्नांडो 68, यह बहुत मददगार है। : - \
हारून बर्ट्रेंड

2

बुनियादी के लिए (वर्तमान सप्ताह का रविवार)

select cast(dateadd(day,-(datepart(dw,getdate())-1),getdate()) as date)

यदि पिछले सप्ताह:

select cast(dateadd(day,-(datepart(dw,getdate())-1),getdate()) -7 as date)

आंतरिक रूप से, हमने एक फ़ंक्शन बनाया जो इसे करता है लेकिन अगर आपको त्वरित और गंदे की आवश्यकता है, तो यह ऐसा करेगा।


0

चूंकि जूलियन तारीख 0 एक सोमवार है, बस सप्ताह की संख्या को रविवार तक जोड़ें, जो -1 ईजी से पहले दिन है। डेटीड (wk, datediff (wk, 0, getdate) (), - 1) का चयन करें


0
Set DateFirst 1;

Select 
    Datepart(wk, TimeByDay) [Week]
    ,Dateadd(d,
                CASE 
                WHEN  Datepart(dw, TimeByDay) = 1 then 0
                WHEN  Datepart(dw, TimeByDay) = 2 then -1
                WHEN  Datepart(dw, TimeByDay) = 3 then -2
                WHEN  Datepart(dw, TimeByDay) = 4 then -3
                WHEN  Datepart(dw, TimeByDay) = 5 then -4
                WHEN  Datepart(dw, TimeByDay) = 6 then -5
                WHEN  Datepart(dw, TimeByDay) = 7 then -6
                END
                , TimeByDay) as StartOfWeek

from TimeByDay_Tbl

यह मेरा तर्क है। सप्ताह का पहला सोमवार निर्धारित करें फिर गणना करें कि सप्ताह का दिन क्या दिन है, फिर DateAdd और Case का उपयोग करके गणना करते हैं कि उस सप्ताह के पिछले सोमवार को क्या तारीख होगी।


-1

मेरे पास यहां दिए गए किसी भी उत्तर के साथ कोई समस्या नहीं है, हालांकि मुझे लगता है कि मेरा कार्यान्वयन करने और समझने के लिए मेरा बहुत सरल है। मैंने इस पर कोई प्रदर्शन परीक्षण नहीं चलाया है, लेकिन यह नीच होना चाहिए।

इसलिए मैंने अपना जवाब इस तथ्य से लिया है कि दिनांक SQL सर्वर में पूर्णांक के रूप में संग्रहीत हैं, (मैं केवल दिनांक घटक के बारे में बात कर रहा हूं)। यदि आप मुझ पर विश्वास नहीं करते हैं, तो इस SELECT CONVERT (INT, GETDATE ()), और इसके विपरीत प्रयास करें।

अब यह जानकर, आप कुछ शांत गणित समीकरण कर सकते हैं। आप एक बेहतर के साथ आने में सक्षम हो सकते हैं, लेकिन यहाँ मेरा है।

/*
TAKEN FROM http://msdn.microsoft.com/en-us/library/ms181598.aspx
First day of the week is
1 -- Monday
2 -- Tuesday
3 -- Wednesday
4 -- Thursday
5 -- Friday
6 -- Saturday
7 (default, U.S. English) -- Sunday
*/

--Offset is required to compensate for the fact that my @@DATEFIRST setting is 7, the default. 
DECLARE @offSet int, @testDate datetime
SELECT @offSet = 1, @testDate = GETDATE()

SELECT CONVERT(DATETIME, CONVERT(INT, @testDate) - (DATEPART(WEEKDAY, @testDate) - @offSet))

1
मुझे लगता है कि यह मेरे लिए काम नहीं करता है। मेरा @@DATEFIRST7 भी है, लेकिन यदि आपकी @testDateसप्ताह की शुरुआत है, तो यह एक तारीख है जो पहले दिन है।
पंक्ति 1

-1

मुझे भी ऐसी ही समस्या का समाधान करना पड़ा था। एक तारीख को देखते हुए, मैं उस सप्ताह के सोमवार की तारीख प्राप्त करना चाहता था।

मैंने निम्नलिखित तर्क का उपयोग किया: 0-6 की सीमा में सप्ताह में दिन की संख्या ज्ञात करें, फिर मूल तिथि से घटाएं।

मैंने उपयोग किया: DATEADD (दिन, - (DATEPART (कार्यदिवस,) + 5)% 7,)

DATEPRRT (कार्यदिवस) के बाद से 1 = रविवार ... 7 = शनिवार, DATEPART (कार्यदिवस, + 5)% 7 रिटर्न 0 = सोमवार ... 6 = रविवार।

मूल तिथि से दिनों की इस संख्या को घटाकर पिछले सोमवार को देता है। सप्ताह के किसी भी शुरुआती दिन एक ही तकनीक का इस्तेमाल किया जा सकता है।


-1

मुझे यह सरल और उपयोगी लगा। भले ही सप्ताह का पहला दिन रविवार या सोमवार हो।

तारीख के रूप में घोषित करें

SET @BaseDate = GETDATE ()

तिथि के रूप में @FrtrtDOW की घोषणा करें

सेलेक्ट करें @FirstDOW = DATEADD (d, DATEPART (WEEKDAY, @ BaseDate) * -1 + 1, @BaseDate)


-3

शायद मैं यहाँ सरल कर रहा हूँ, और यह मामला हो सकता है, लेकिन यह मेरे लिए काम करने लगता है। अभी तक इसके साथ कोई समस्या नहीं हुई ...

CAST('1/1/' + CAST(YEAR(GETDATE()) AS VARCHAR(30)) AS DATETIME) + (DATEPART(wk, YOUR_DATE) * 7 - 7) as 'FirstDayOfWeek'
CAST('1/1/' + CAST(YEAR(GETDATE()) AS VARCHAR(30)) AS DATETIME) + (DATEPART(wk, YOUR_DATE) * 7) as 'LastDayOfWeek'

यदि आप अलग-अलग सेटिंग्स के लिए प्रयास करते हैं, तो आप यहां विभिन्न उत्तर प्राप्त कर सकते हैं SET DATEFIRST
हारून बर्ट्रेंड

5
खैर, मैंने वोट नहीं डाला, लेकिन आपके जवाब DATEFIRSTमें अभी (साढ़े तीन साल के लिए) का उल्लेख नहीं था , और अभी भी नहीं है। और आपको क्षेत्रीय प्रारूपों से भी बचना चाहिए m/d/y, यहां तक ​​कि उन परिदृश्यों में भी जहां एम और डी समान हैं।
हारून बर्ट्रेंड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.