Uzyskaj datę rozpoczęcia tygodnia i datę zakończenia tygodnia na podstawie numeru tygodnia


98

Mam zapytanie, które zlicza daty ślubu członka w bazie danych.

SELECT 
  SUM(NumberOfBrides) AS [Wedding Count]
  , DATEPART( wk, WeddingDate) AS [Week Number]
  , DATEPART( year, WeddingDate) AS [Year]
FROM  MemberWeddingDates
GROUP BY DATEPART(year, WeddingDate), DATEPART(wk, WeddingDate)
ORDER BY SUM(NumberOfBrides) DESC

Jak obliczyć, kiedy początek i koniec każdego tygodnia są przedstawione w zestawie wyników?

SELECT
  SUM(NumberOfBrides) AS [Wedding Count]
  , DATEPART(wk, WeddingDate) AS [Week Number]
  , DATEPART(year, WeddingDate) AS [Year]
  , ??? AS WeekStart
  , ??? AS WeekEnd
FROM  MemberWeddingDates
GROUP BY DATEPART(year, WeddingDate), DATEPART(wk, WeddingDate)
ORDER BY SUM(NumberOfBrides) DESC

Odpowiedzi:


161

Możesz znaleźć dzień tygodnia i dodać dni, aby uzyskać datę początkową i końcową.

DATEADD(dd, -(DATEPART(dw, WeddingDate)-1), WeddingDate) [WeekStart]

DATEADD(dd, 7-(DATEPART(dw, WeddingDate)), WeddingDate) [WeekEnd]

Prawdopodobnie chcesz również spojrzeć na usunięcie czasu z daty.


3
Pamiętaj, że ustawienie DATEFIRSTcokolwiek innego niż 7 przerywa to.
Tomalak,

5
Nie "zepsuje" go, użyje datefirst do ustawienia WeekStart = na to, co DateFirst mówi, że jest pierwszym dniem tygodnia. Twoja wersja będzie zawsze działać w poniedziałek i niedzielę jako początek i koniec tygodnia, a nie to, co serwer ma używać jako początek i koniec tygodnia
Robin Day,

1
Hm ... To ważny punkt, +1. :) W takim razie skasuję moje (chociaż jak na strzał w stopę, było bardzo dobrze wycelowane. G ).
Tomalak

1
Cóż, w takim razie ponownie go cofam. Nie jestem pewien, kto przy zdrowych zmysłach i tak założyłby cokolwiek innego niż poniedziałek jako początek tygodnia. Aby rozpocząć tydzień w niedzielę nie ma sensu w ogóle . :-)
Tomalak

3
„set datefirst 1” na poniedziałek ( msdn.microsoft.com/en-ie/library/ms181598.aspx )
Selrac

41

Oto DATEFIRSTrozwiązanie agnostyczne:

SET DATEFIRST 4     /* or use any other weird value to test it */
DECLARE @d DATETIME

SET @d = GETDATE()

SELECT
  @d ThatDate,
  DATEADD(dd, 0 - (@@DATEFIRST + 5 + DATEPART(dw, @d)) % 7, @d) Monday,
  DATEADD(dd, 6 - (@@DATEFIRST + 5 + DATEPART(dw, @d)) % 7, @d) Sunday

11
To świetnie, ale poniedziałek mi nie wyszedł. Musiałem dodać „0 -”, żeby otrzymać poniedziałki. Mój poniedziałkowy kod to teraz: DATEADD (dd, 0 - (@@ DATEFIRST + 5 + DATEPART (dw, @d))% 7, @d)
Warren

Głosował za odpowiedzią i komentarzem Warrensa. Sql Server w wersji 11.0.5058.0 podaje co najmniej nieprawidłową datę poniedziałku bez modyfikacji Warrens. Zamiast tego dawał mi piątek.
Morvael

18

możesz również użyć tego:

  SELECT DATEADD(day, DATEDIFF(day, 0, WeddingDate) /7*7, 0) AS weekstart,
         DATEADD(day, DATEDIFF(day, 6, WeddingDate-1) /7*7 + 7, 6) AS WeekEnd

2

Poszerzenie odpowiedzi @ Tomalak . Formuła działa dla dni innych niż niedziela i poniedziałek, ale musisz użyć innych wartości dla miejsca, w którym znajduje się 5. Sposobem na osiągnięcie wartości, której potrzebujesz, jest

Value Needed = 7 - (Value From Date First Documentation for Desired Day Of Week) - 1

tutaj jest link do dokumentu: https://msdn.microsoft.com/en-us/library/ms181598.aspx

A oto stół, który to przedstawia.

          | DATEFIRST VALUE |   Formula Value   |   7 - DATEFIRSTVALUE - 1
Monday    | 1               |          5        |   7 - 1- 1 = 5
Tuesday   | 2               |          4        |   7 - 2 - 1 = 4
Wednesday | 3               |          3        |   7 - 3 - 1 = 3
Thursday  | 4               |          2        |   7 - 4 - 1 = 2
Friday    | 5               |          1        |   7 - 5 - 1 = 1
Saturday  | 6               |          0        |   7 - 6 - 1 = 0
Sunday    | 7               |         -1        |   7 - 7 - 1 = -1

Ale nie musisz pamiętać tej tabeli i tylko wzoru, a właściwie możesz użyć nieco innej tabeli, główną potrzebą jest użycie wartości, która sprawi, że pozostała część będzie prawidłową liczbą dni.

Oto działający przykład:

DECLARE @MondayDateFirstValue INT = 1
DECLARE @FridayDateFirstValue INT = 5
DECLARE @TestDate DATE = GETDATE()

SET @MondayDateFirstValue = 7 - @MondayDateFirstValue - 1
SET @FridayDateFirstValue = 7 - @FridayDateFirstValue - 1

SET DATEFIRST 6 -- notice this is saturday

SELECT 
    DATEADD(DAY, 0 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate)  as MondayStartOfWeek
    ,DATEADD(DAY, 6 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as MondayEndOfWeek
   ,DATEADD(DAY, 0 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate)  as FridayStartOfWeek
    ,DATEADD(DAY, 6 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as FridayEndOfWeek


SET DATEFIRST 2 --notice this is tuesday

SELECT 
    DATEADD(DAY, 0 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate)  as MondayStartOfWeek
    ,DATEADD(DAY, 6 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as MondayEndOfWeek
   ,DATEADD(DAY, 0 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate)  as FridayStartOfWeek
    ,DATEADD(DAY, 6 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as FridayEndOfWeek

Ta metoda byłaby niezależna od DATEFIRSTustawienia, którego potrzebowałem, ponieważ buduję wymiar daty z uwzględnieniem metod wielotygodniowych.


2

Oto inna wersja. Jeśli Twój Scenariusz wymaga, aby sobota była pierwszym dniem tygodnia, a piątek ostatnim dniem tygodnia, poniższy kod zajmie się tym:

  DECLARE @myDate DATE = GETDATE()
  SELECT    @myDate,
    DATENAME(WEEKDAY,@myDate),
    DATEADD(DD,-(CHOOSE(DATEPART(dw, @myDate), 1,2,3,4,5,6,0)),@myDate) AS WeekStartDate,
    DATEADD(DD,7-CHOOSE(DATEPART(dw, @myDate), 2,3,4,5,6,7,1),@myDate) AS WeekEndDate

Zrzut ekranu zapytania


1

Poniższe zapytanie poda dane od początku do końca bieżącego tygodnia od niedzieli do soboty

SELECT DOB FROM PROFILE_INFO WHERE DAY(DOB) BETWEEN
DAY( CURRENT_DATE() - (SELECT DAYOFWEEK(CURRENT_DATE())-1))
AND
DAY((CURRENT_DATE()+(7 - (SELECT DAYOFWEEK(CURRENT_DATE())) ) ))
AND
MONTH(DOB)=MONTH(CURRENT_DATE())

1

Podzielmy problem na dwie części:

1) Określ dzień tygodnia

W DATEPART(dw, ...)Zwraca liczbę, 1 ... 7, w stosunku do DATEFIRSTustawienia ( dokumenty ). W poniższej tabeli podsumowano możliwe wartości:

                                                   @@DATEFIRST
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
|                                    |  1  |  2  |  3  |  4  |  5  |  6  |  7  | DOW |
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
|  DATEPART(dw, /*Mon*/ '20010101')  |  1  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
|  DATEPART(dw, /*Tue*/ '20010102')  |  2  |  1  |  7  |  6  |  5  |  4  |  3  |  2  |
|  DATEPART(dw, /*Wed*/ '20010103')  |  3  |  2  |  1  |  7  |  6  |  5  |  4  |  3  |
|  DATEPART(dw, /*Thu*/ '20010104')  |  4  |  3  |  2  |  1  |  7  |  6  |  5  |  4  |
|  DATEPART(dw, /*Fri*/ '20010105')  |  5  |  4  |  3  |  2  |  1  |  7  |  6  |  5  |
|  DATEPART(dw, /*Sat*/ '20010106')  |  6  |  5  |  4  |  3  |  2  |  1  |  7  |  6  |
|  DATEPART(dw, /*Sun*/ '20010107')  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  7  |
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+

Ostatnia kolumna zawiera idealną wartość dnia tygodnia dla tygodni od poniedziałku do niedzieli *. Po prostu patrząc na wykres, otrzymujemy następujące równanie:

(@@DATEFIRST + DATEPART(dw, SomeDate) - 1 - 1) % 7 + 1

2) Oblicz poniedziałek i niedzielę dla podanej daty

Jest to trywialne dzięki wartości dnia tygodnia. Oto przykład:

WITH TestData(SomeDate) AS (
    SELECT CAST('20001225' AS DATETIME) UNION ALL
    SELECT CAST('20001226' AS DATETIME) UNION ALL
    SELECT CAST('20001227' AS DATETIME) UNION ALL
    SELECT CAST('20001228' AS DATETIME) UNION ALL
    SELECT CAST('20001229' AS DATETIME) UNION ALL
    SELECT CAST('20001230' AS DATETIME) UNION ALL
    SELECT CAST('20001231' AS DATETIME) UNION ALL
    SELECT CAST('20010101' AS DATETIME) UNION ALL
    SELECT CAST('20010102' AS DATETIME) UNION ALL
    SELECT CAST('20010103' AS DATETIME) UNION ALL
    SELECT CAST('20010104' AS DATETIME) UNION ALL
    SELECT CAST('20010105' AS DATETIME) UNION ALL
    SELECT CAST('20010106' AS DATETIME) UNION ALL
    SELECT CAST('20010107' AS DATETIME) UNION ALL
    SELECT CAST('20010108' AS DATETIME) UNION ALL
    SELECT CAST('20010109' AS DATETIME) UNION ALL
    SELECT CAST('20010110' AS DATETIME) UNION ALL
    SELECT CAST('20010111' AS DATETIME) UNION ALL
    SELECT CAST('20010112' AS DATETIME) UNION ALL
    SELECT CAST('20010113' AS DATETIME) UNION ALL
    SELECT CAST('20010114' AS DATETIME)
), TestDataPlusDOW AS (
    SELECT SomeDate, (@@DATEFIRST + DATEPART(dw, SomeDate) - 1 - 1) % 7 + 1 AS DOW
    FROM TestData
)
SELECT
    FORMAT(SomeDate,                            'ddd yyyy-MM-dd') AS SomeDate,
    FORMAT(DATEADD(dd, -DOW + 1, SomeDate),     'ddd yyyy-MM-dd') AS [Monday],
    FORMAT(DATEADD(dd, -DOW + 1 + 6, SomeDate), 'ddd yyyy-MM-dd') AS [Sunday]
FROM TestDataPlusDOW

Wynik:

+------------------+------------------+------------------+
|  SomeDate        |  Monday          |    Sunday        |
+------------------+------------------+------------------+
|  Mon 2000-12-25  |  Mon 2000-12-25  |  Sun 2000-12-31  |
|  Tue 2000-12-26  |  Mon 2000-12-25  |  Sun 2000-12-31  |
|  Wed 2000-12-27  |  Mon 2000-12-25  |  Sun 2000-12-31  |
|  Thu 2000-12-28  |  Mon 2000-12-25  |  Sun 2000-12-31  |
|  Fri 2000-12-29  |  Mon 2000-12-25  |  Sun 2000-12-31  |
|  Sat 2000-12-30  |  Mon 2000-12-25  |  Sun 2000-12-31  |
|  Sun 2000-12-31  |  Mon 2000-12-25  |  Sun 2000-12-31  |
|  Mon 2001-01-01  |  Mon 2001-01-01  |  Sun 2001-01-07  |
|  Tue 2001-01-02  |  Mon 2001-01-01  |  Sun 2001-01-07  |
|  Wed 2001-01-03  |  Mon 2001-01-01  |  Sun 2001-01-07  |
|  Thu 2001-01-04  |  Mon 2001-01-01  |  Sun 2001-01-07  |
|  Fri 2001-01-05  |  Mon 2001-01-01  |  Sun 2001-01-07  |
|  Sat 2001-01-06  |  Mon 2001-01-01  |  Sun 2001-01-07  |
|  Sun 2001-01-07  |  Mon 2001-01-01  |  Sun 2001-01-07  |
|  Mon 2001-01-08  |  Mon 2001-01-08  |  Sun 2001-01-14  |
|  Tue 2001-01-09  |  Mon 2001-01-08  |  Sun 2001-01-14  |
|  Wed 2001-01-10  |  Mon 2001-01-08  |  Sun 2001-01-14  |
|  Thu 2001-01-11  |  Mon 2001-01-08  |  Sun 2001-01-14  |
|  Fri 2001-01-12  |  Mon 2001-01-08  |  Sun 2001-01-14  |
|  Sat 2001-01-13  |  Mon 2001-01-08  |  Sun 2001-01-14  |
|  Sun 2001-01-14  |  Mon 2001-01-08  |  Sun 2001-01-14  |
+------------------+------------------+------------------+

* W tygodniach od niedzieli do soboty wystarczy trochę skorygować równanie, np. Dodać gdzieś 1.


1

Jeśli niedziela jest traktowana jako dzień rozpoczęcia tygodnia, oto kod

Declare @currentdate date = '18 Jun 2020'

select DATEADD(D, -(DATEPART(WEEKDAY, @currentdate) - 1), @currentdate)

select DATEADD(D, (7 - DATEPART(WEEKDAY, @currentdate)), @currentdate)

0

Po prostu napotykam podobny przypadek z tym, ale tutaj rozwiązanie wydaje mi się nie pomagać. Więc próbuję to rozgryźć sam. Wyliczam tylko datę rozpoczęcia tygodnia, data zakończenia tygodnia powinna mieć podobną logikę.

Select 
      Sum(NumberOfBrides) As [Wedding Count], 
      DATEPART( wk, WeddingDate) as [Week Number],
      DATEPART( year, WeddingDate) as [Year],
      DATEADD(DAY, 1 - DATEPART(WEEKDAY, dateadd(wk, DATEPART( wk, WeddingDate)-1,  DATEADD(yy,DATEPART( year, WeddingDate)-1900,0))), dateadd(wk, DATEPART( wk, WeddingDate)-1, DATEADD(yy,DATEPART( year, WeddingDate)-1900,0))) as [Week Start]

FROM  MemberWeddingDates
Group By DATEPART( year, WeddingDate), DATEPART( wk, WeddingDate)
Order By Sum(NumberOfBrides) Desc

0

Najczęściej głosowana odpowiedź działa dobrze, z wyjątkiem pierwszego tygodnia i ostatniego tygodnia roku. Na przykład, jeżeli wartość WeddingDate jest „01.01.2016”, wynik będzie 27/12/2015 i 02/01/2016 , ale prawidłowa odpowiedź jest 01.01.2016 i 2.01.2016 .

Spróbuj tego:

Select 
  Sum(NumberOfBrides) As [Wedding Count], 
  DATEPART( wk, WeddingDate) as [Week Number],
  DATEPART( year, WeddingDate) as [Year],
  MAX(CASE WHEN DATEPART(WEEK, WeddingDate) = 1 THEN CAST(DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0) AS date) ELSE DATEADD(DAY, 7 * DATEPART(WEEK, WeddingDate), DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0))) END) as WeekStart,
  MAX(CASE WHEN DATEPART(WEEK, WeddingDate) = DATEPART(WEEK, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate) + 1, 0))) THEN DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate) + 1, 0)) ELSE DATEADD(DAY, 7 * DATEPART(WEEK, WeddingDate) + 6, DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0))) END) as WeekEnd
FROM  MemberWeddingDates
Group By DATEPART( year, WeddingDate), DATEPART( wk, WeddingDate)
Order By Sum(NumberOfBrides) Desc;

Wynik wygląda następująco: wprowadź opis obrazu tutaj

Działa przez wszystkie tygodnie, pierwszy lub inny.


0

Tydzień data rozpoczęcia i zakończenia od daty dla formuły usługi Power BI Dax

WeekStartDate = [DateColumn] - (WEEKDAY([DateColumn])-1)
WeekEndDate = [DateColumn] + (7-WEEKDAY([DateColumn]))

0

To jest moje rozwiązanie

    SET DATEFIRST 1; / * zmień, aby użyć innej daty, najpierw * /
    ZADEKLAROWAĆ @date DATETIME
    SET @date = CAST ('2/6/2019' jako data)

    SELECT DATEADD (dd, 0 - (DATEPART (dw, @date) - 1), @ date) [dateFrom], 
            DATEADD (dd, 6 - (DATEPART (dw, @date) - 1), @ date) [dateTo]


0

Uzyskaj datę rozpoczęcia i datę zakończenia według daty niestandardowej


   DECLARE @Date NVARCHAR(50)='05/19/2019' 
   SELECT
      DATEADD(DAY,CASE WHEN DATEPART(WEEKDAY, @Date)=1 THEN -6 ELSE 2 - DATEPART(WEEKDAY, @Date) END, CAST(@Date AS DATE)) [Week_Start_Date]
     ,DATEADD(DAY,CASE WHEN DATEPART(WEEKDAY, @Date)=1 THEN 0 ELSE  8 - DATEPART(WEEKDAY, @Date) END, CAST(@Date AS DATE)) [Week_End_Date]


Chociaż ten kod może rozwiązać problem, dołączenie wyjaśnienia naprawdę pomaga poprawić jakość twojego postu.
Shree

0

Mam inny sposób, to wybierz dzień Początek i dzień Koniec tygodnia Aktualny:

DATEADD (d, - (DATEPART (dw, GETDATE () - 2)), GETDATE ()) to data i godzina Początek

i

DATEADD (dzień, 7- (DATEPART (dw, GETDATE () - 1)), GETDATE ()) to data i godzina Koniec


0

Inny sposób na zrobienie tego:

declare @week_number int = 6280 -- 2020-05-07
declare @start_weekday int = 0 -- Monday
declare @end_weekday int = 6 -- next Sunday

select 
    dateadd(week, @week_number, @start_weekday), 
    dateadd(week, @week_number, @end_weekday)

Wyjaśnienie:

  • @week_number to numer tygodnia od początkowej daty kalendarza „ 1900-01-01 ”. Można to obliczyć w ten sposób:select datediff(week, 0, @wedding_date) as week_number
  • @start_weekday dla pierwszego dnia tygodnia: 0 dla poniedziałku, -1 dla niedzieli
  • @end_weekday dla tygodnia, ostatni dzień: 6 dla następnej niedzieli, 5 dla soboty
  • dateadd(week, @week_number, @end_weekday): dodaje podaną liczbę tygodni i podaną liczbę dni do początkowej daty kalendarza „ 1900-01-01

0

To nie pochodzi ode mnie, ale wykonało swoją pracę niezależnie:

SELECT DATEADD(wk, -1, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day previous week
SELECT DATEADD(wk, 0, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day current week
SELECT DATEADD(wk, 1, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day next week

SELECT DATEADD(wk, 0, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day previous week
SELECT DATEADD(wk, 1, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day current week
SELECT DATEADD(wk, 2, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day next week

Znalazłem to tutaj .


-3

Nie jestem pewien, jak przydatne jest to, ale skończyłem tutaj, szukając rozwiązania na Netezza SQL i nie mogłem go znaleźć przy przepełnieniu stosu.

W przypadku IBM netezza użyłbyś czegoś (na początek tygodnia w poniedziałek, koniec tygodnia) na przykład:

wybierz next_day (WeddingDate, 'SUN') -6 jako WeekStart,

next_day (WeddingDate, 'SUN') jako WeekEnd


-4

w przypadku zapytań dostępu można użyć jako pola w poniższym formacie

"FirstDayofWeek:IIf(IsDate([ForwardedForActionDate]),CDate(Format([ForwardedForActionDate],"dd/mm/yyyy"))-(Weekday([ForwardedForActionDate])-1))"

dozwolone bezpośrednie obliczenia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.