Lấy ngày bắt đầu tuần và ngày kết thúc tuần từ số tuần


98

Tôi có một truy vấn đếm ngày cưới của thành viên trong cơ sở dữ liệu.

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

Làm cách nào để tìm ra khi bắt đầu và kết thúc mỗi tuần được thể hiện trong tập kết quả?

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

Câu trả lời:


161

Bạn có thể tìm ngày trong tuần và thêm ngày vào các ngày để có ngày bắt đầu và ngày kết thúc ..

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

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

Bạn có thể cũng muốn xem xét việc loại bỏ thời gian từ ngày.


3
Hãy nhớ rằng cài đặt DATEFIRSTthành bất kỳ điều gì khác ngoài 7 sẽ phá vỡ điều này.
Tomalak

5
Nó sẽ không "phá vỡ" nó, nó sẽ sử dụng datefirst để đặt WeekStart = thành những gì DateFirst cho biết ngày đầu tiên của một tuần là. Phiên bản của bạn sẽ luôn hoạt động vào Thứ Hai và Chủ Nhật khi bắt đầu và kết thúc một tuần, không phải những gì máy chủ được thiết lập để sử dụng làm đầu và cuối tuần
Robin Day

1
Hm ... Đó là một điểm hợp lệ, +1. :) Tôi sẽ xóa của tôi, sau đó (Mặc dù là một phát bắn vào chân, nó được nhắm cực kỳ tốt. G ).
Tomalak

1
Vâng, sau đó tôi phục hồi nó một lần nữa. Tôi không chắc ai trong tâm trí họ sẽ giả định bất cứ điều gì khác ngoài thứ Hai là ngày đầu tuần. Bắt đầu một tuần vào Chủ nhật không có ý nghĩa . :-)
Tomalak

3
'đặt datefirst 1' cho Thứ Hai ( msdn.microsoft.com/en-ie/library/ms181598.aspx )
Selrac

41

Đây là một DATEFIRSTgiải pháp bất khả tri:

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
Điều này thật tuyệt, nhưng ngày thứ Hai không phù hợp với tôi. Tôi phải thêm "0 -" để có được Thứ Hai. Mã Thứ Hai của tôi bây giờ là: DATEADD (dd, 0 - (@@ DATEFIRST + 5 + DATEPART (dw, @d))% 7, @d)
Warren

Đã ủng hộ cả câu trả lời và bình luận của Warrens. Ít nhất thì phiên bản máy chủ Sql 11.0.5058.0 đưa ra sai ngày cho Thứ Hai mà không có sửa đổi Cảnh báo. Thay vào đó đã cho tôi thứ sáu.
Morvael

18

bạn cũng có thể sử dụng cái này:

  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

Mở rộng câu trả lời của @ Tomalak . Công thức hoạt động cho các ngày không phải Chủ nhật và Thứ hai nhưng bạn cần sử dụng các giá trị khác nhau cho vị trí của 5. Một cách để đạt được giá trị bạn cần là

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

đây là một liên kết đến tài liệu: https://msdn.microsoft.com/en-us/library/ms181598.aspx

Và đây là một bảng đặt nó ra cho bạn.

          | 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

Nhưng bạn không cần phải nhớ bảng đó và chỉ công thức, và thực sự bạn có thể sử dụng một bảng hơi khác vì nhu cầu chính là sử dụng một giá trị sẽ làm cho phần còn lại là số ngày chính xác.

Đây là một ví dụ hoạt động:

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

Phương pháp này sẽ không phù hợp với DATEFIRSTCài đặt, đó là những gì tôi cần khi tôi đang xây dựng thứ nguyên ngày với các phương pháp nhiều tuần được bao gồm.


2

Đây là một phiên bản khác. Nếu Kịch bản của bạn yêu cầu Thứ Bảy là ngày đầu tiên của Tuần và Thứ Sáu là ngày cuối cùng của Tuần, thì đoạn mã dưới đây sẽ xử lý điều đó:

  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

Ảnh chụp màn hình của Truy vấn


1

Truy vấn bên dưới sẽ cung cấp dữ liệu từ đầu đến cuối tuần hiện tại, bắt đầu từ chủ nhật đến thứ bảy

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

Hãy để chúng tôi chia vấn đề thành hai phần:

1) Xác định ngày trong tuần

Trả DATEPART(dw, ...)về một số, 1 ... 7, liên quan đến DATEFIRSTcài đặt ( tài liệu ). Bảng sau đây tóm tắt các giá trị có thể có:

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

Cột cuối cùng chứa giá trị ngày trong tuần lý tưởng cho các tuần từ Thứ Hai đến Chủ Nhật *. Chỉ cần nhìn vào biểu đồ, chúng tôi đưa ra phương trình sau:

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

2) Tính thứ hai và chủ nhật cho ngày nhất định

Điều này là nhỏ nhờ vào giá trị ngày trong tuần. Đây là một ví dụ:

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

Đầu ra:

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

* Đối với các tuần từ Chủ nhật đến Thứ bảy, bạn chỉ cần điều chỉnh phương trình một chút, chẳng hạn như thêm 1 vào đâu đó.


1

Nếu chủ nhật được coi là ngày bắt đầu của tuần, thì đây là mã

Declare @currentdate date = '18 Jun 2020'

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

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

0

Tôi vừa gặp trường hợp tương tự với trường hợp này, nhưng giải pháp ở đây dường như không giúp được tôi. Vì vậy, tôi cố gắng tìm ra nó một mình. Tôi chỉ tính toán ngày bắt đầu tuần, ngày kết thúc tuần phải có logic tương tự.

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

Câu trả lời được bình chọn nhiều nhất hoạt động tốt ngoại trừ tuần đầu tiên và tuần cuối cùng của năm. Ví dụ: nếu giá trị của WeddingDate là '2016-01-01', kết quả sẽ là 2015-12-272016-01-02 , nhưng câu trả lời đúng là 2016-01-012016-01-02 .

Thử cái này:

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;

Kết quả trông giống như: nhập mô tả hình ảnh ở đây

Nó hoạt động cho tất cả các tuần, đầu tiên hoặc những người khác.


0

Ngày bắt đầu và kết thúc tuần Từ ngày Đối với Công thức Power BI Dax

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

0

Đây là giải pháp của tôi

    ĐẶT DATEFIRST 1; / * thay đổi để sử dụng một ngày đầu tiên khác * /
    DECLARE @date DATETIME
    SET @date = CAST ('2/6/2019' là ngày)

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


0

Lấy ngày bắt đầu và ngày kết thúc theo ngày tùy chỉnh


   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]


Mặc dù mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn.
Shree

0

Tôi có một cách khác, đó là chọn ngày Bắt đầu và ngày Cuối tuần Hiện tại:

DATEADD (d, - (DATEPART (dw, GETDATE () - 2)), GETDATE ()) là ngày giờ Bắt đầu

DATEADD (ngày, 7- (DATEPART (dw, GETDATE () - 1)), GETDATE ()) là ngày giờ Kết thúc


0

Một cách khác để làm điều đó:

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)

Giải trình:

  • @week_number là số tuần kể từ ngày lịch đầu tiên ' 1900-01-01 '. Nó có thể được tính theo cách này:select datediff(week, 0, @wedding_date) as week_number
  • @start_weekday cho ngày đầu tiên của tuần: 0 cho Thứ Hai, -1 nếu Chủ Nhật
  • @end_weekday cho tuần trước: 6 cho Chủ Nhật tới, 5 cho Thứ Bảy
  • dateadd(week, @week_number, @end_weekday): thêm số tuần nhất định và số ngày nhất định vào ngày lịch ban đầu ' 1900-01-01 '

0

Điều này không đến từ tôi, nhưng nó đã hoàn thành công việc bất kể:

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

Tôi tìm thấy nó ở đây .


-3

Không chắc điều này hữu ích như thế nào, nhưng tôi đã kết thúc ở đây từ việc tìm kiếm một giải pháp trên Netezza SQL và không thể tìm thấy một giải pháp khi tràn ngăn xếp.

Đối với IBM netezza, bạn sẽ sử dụng một cái gì đó (cho tuần bắt đầu, cuối tuần cuối tuần) như:

chọn next_day (WeddingDate, 'SUN') -6 làm WeekStart,

next_day (WeddingDate, 'SUN') là WeekEnd


-4

đối với Truy vấn Access, bạn có thể sử dụng ở định dạng dưới đây làm trường

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

được phép tính toán trực tiếp ..

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.