Отримайте дату початку тижня та дату закінчення тижня з номера тижня


98

У мене є запит, який підраховує дати весілля учасника в базі даних.

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

Як я можу визначити, коли початок і кінець кожного тижня представлені у наборі результатів?

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

Відповіді:


161

Ви можете знайти день тижня та додати дату за днями, щоб отримати дати початку та кінця.

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

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

Ви, ймовірно, також хочете поглянути на те, щоб позбавити часу від дати.


3
Майте на увазі, що встановлення DATEFIRSTбудь-чого, крім 7, порушує це.
Томалак

5
Він не "зламає" його, він буде використовувати datefirst, щоб встановити WeekStart = до того, що DateFirst каже, що це перший день тижня. Ваша версія завжди робитиме понеділок та неділю як початок та кінець тижня, а не те, що сервер призначений використовувати як початок та кінець тижня
День Робін

1
Хм ... Це дійсний бал, +1. :) Тоді я видалю свій (Хоча за постріл у ногу він був надзвичайно добре націлений. G ).
Томалак

1
Ну, тоді я знову видаляю це. Я не впевнений, хто б у здоровому розумі все-таки взяв за початок тижня щось, крім понеділка. Починати тиждень у неділю взагалі немає сенсу . :-)
Томалак

3
'встановити першу дату 1' для понеділка ( msdn.microsoft.com/en-ie/library/ms181598.aspx )
Селрак

41

Ось DATEFIRSTагностичне рішення:

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
Це чудово, але понеділок для мене не працював. Мені довелося додати "0 -", щоб отримати понеділок. Зараз мій код понеділка: DATEADD (dd, 0 - (@@ DATEFIRST + 5 + DATEPART (dw, @d))% 7, @d)
Уоррен

Підтримали як відповідь, так і коментар Warrens. Sql Server версії 11.0.5058.0 принаймні дає неправильну дату понеділка без модифікації Warrens. Натомість давав мені п’ятницю.
Морваел

18

Ви також можете використовувати це:

  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

Розширюючи відповідь @ Tomalak . Формула працює для інших днів, крім неділі та понеділка, але вам потрібно використовувати різні значення, де 5. Спосіб досягти потрібного вам значення є

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

ось посилання на документ: https://msdn.microsoft.com/en-us/library/ms181598.aspx

І ось таблиця, яка викладає це для вас.

          | 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

Але вам не потрібно пам’ятати цю таблицю та лише формулу, і насправді ви могли б використовувати і дещо іншу, головна потреба полягає у використанні значення, яке зробить для решти правильну кількість днів.

Ось робочий приклад:

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

Цей метод був би агностичним щодо DATEFIRSTналаштування, яке мені потрібно, оскільки я будую вимірювання дати, включаючи кілька тижневих методів.


2

Ось ще одна версія. Якщо ваш сценарій вимагає, щоб субота була першим днем ​​тижня, а п’ятниця - останнім днем ​​тижня, нижченаведений код розгляне це:

  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

Знімок екрана запиту


1

Нижче запит дасть дані між початком та кінцем поточного тижня, починаючи з неділі до суботи

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

Розкладемо проблему на дві частини:

1) Визначте день тижня

У DATEPART(dw, ...)повертає число, 1 ... 7, щодо DATEFIRSTустановки ( документи ). Наступна таблиця узагальнює можливі значення:

                                                   @@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  |
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+

Останній стовпець містить ідеальне значення дня тижня для тижня з понеділка по неділю *. Поглянувши на діаграму, ми отримуємо таке рівняння:

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

2) Обчисліть понеділок та неділю для заданої дати

Це тривіально завдяки значенню дня тижня. Ось приклад:

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

Вихід:

+------------------+------------------+------------------+
|  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  |
+------------------+------------------+------------------+

* Для тижнів з неділі по суботу потрібно трохи відкоригувати рівняння, наприклад додати десь 1.


1

Якщо неділя вважається днем ​​початку тижня, то ось код

Declare @currentdate date = '18 Jun 2020'

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

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

0

Я просто стикаюся з подібним випадком із цим, але вирішення тут, здається, мені не допомагає. Тому я намагаюся це зрозуміти самостійно. Я розробляю лише дату початку тижня, дата закінчення тижня повинна бути подібною логікою.

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

Відповідь, за якою проголосували найбільше, працює добре, за винятком 1-го тижня та останнього тижня року. Наприклад, якщо значення WeddingDate - "01.01.2016", результатом буде 27.12.2015 та 02.01.2016 , але правильна відповідь - 01.01.2016 та 02.01.2016 .

Спробуйте це:

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;

Результат виглядає так: введіть тут опис зображення

Це працює протягом усіх тижнів, 1-го або інших.


0

Дата початку та закінчення тижня з дати для формули Power BI Dax

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

0

Це моє рішення

    ВСТАНОВИТИ ПЕРШИЙ 1; / * змініть, щоб використовувати іншу дату спочатку * /
    ЗАЯВИТИ @date DATETIME
    SET @date = CAST (`` 06.02.2019 '' як дата)

    ВИБЕРИТЕ ДАТУ ДОДАТОК (dd, 0 - (DATEPART (dw, @date) - 1), @ date) [dateFrom], 
            DATEADD (dd, 6 - (DATEPART (dw, @date) - 1), @ date) [dateTo]


0

Отримати дату початку та дату закінчення за спеціальною датою


   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]


Хоча цей код може вирішити питання, включення пояснення дійсно допомагає поліпшити якість вашої публікації.
Шрі

0

У мене є інший шлях, це обраний день Початок та день Кінець тижня Поточний:

DATEADD (d, - (DATEPART (dw, GETDATE () - 2)), GETDATE ()) - дата і час Початок

і

DATEADD (день, 7- (DATEPART (dw, GETDATE () - 1)), GETDATE () - дата і час Кінець


0

Ще один спосіб зробити це:

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)

Пояснення:

  • @week_number - це номер тижня з початкової календарної дати ' 1900-01-01 '. Це можна обчислити таким чином:select datediff(week, 0, @wedding_date) as week_number
  • @start_weekday за перший день тижня: 0 для понеділка, -1 якщо неділя
  • @end_weekday за тиждень минулого дня: 6 для наступної неділі, 5 якщо субота
  • dateadd(week, @week_number, @end_weekday): додає задану кількість тижнів та вказану кількість днів до початкової календарної дати ' 1900-01-01 '

0

Це не від мене, але роботу виконано незалежно:

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

Я знайшов його тут .


-3

Не впевнений, наскільки це корисно, але я опинився тут, шукаючи рішення на Netezza SQL, і не міг знайти його при переповненні стека.

Для IBM netezza ви могли б використовувати щось (для початку тижня, пн, кінця тижня), наприклад:

виберіть next_day (WeddingDate, 'SUN') -6 як WeekStart,

next_day (WeddingDate, 'SUN') як WeekEnd


-4

для запитів доступу ви можете використовувати формат, наведений нижче, як поле

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

прямий розрахунок дозволений ..

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.