Nhận ngày trong tuần trong SQL Server 2005/2008


369

Nếu tôi có một ngày 01/01/2009, tôi muốn tìm hiểu ngày nào là ngày thứ Hai, thứ Ba, v.v ...

Có chức năng tích hợp sẵn cho việc này trong SQL Server 2005/2008 không? Hay tôi cần sử dụng bảng phụ?


1
Nếu bạn có một bảng chứa tra cứu cho các phần ngày, bạn thường đã làm sai điều gì đó. Các hàm ngày của SQL Server rất nhiều và mạnh mẽ, vì vậy mọi dữ liệu bạn cần trích xuất từ ​​một ngày đều có thể được thực hiện dễ dàng trên cột datetime.
Benjamin Autin

6
bảng phụ trợ rất hữu ích cho việc tính toán ngày, không có gì lạ khi có bảng phụ trợ lịch ...

2
"Hữu ích cho tính toán ngày" rất đáng ngờ. Hầu hết các tính toán ngày có thể được xử lý mà không cần bất kỳ loại bảng phụ trợ nào và cũng sẽ hoạt động tốt hơn. Trong một số trường hợp, một bảng Số đơn giản sẽ thực hiện công việc - không cần một bảng có ngày thực tế trong đó. Lý do duy nhất tôi thấy rằng một bảng lịch thực sự cần thiết là khi các quy tắc cho ngày nào là ngày làm việc và ngày nào không quá phức tạp. Những gì tôi đã thấy quá thường xuyên là mọi người sử dụng bảng ngày vì họ không biết làm cách nào khác. Sau đó, họ phải thường xuyên điền vào bảng ngày. Ngớ ngẩn.
ErikE

5
Tôi sẽ ăn lời nếu bạn có thể chỉ cho tôi cách sử dụng cho các bảng lịch mà 1) không dành cho quy tắc ngày nghỉ / ngày làm việc phức tạp, 2) không thể thực hiện dễ dàng với các hàm tích hợp và 3) chỉ khi không # 2, sau đó một bảng Số cũng hoạt động tốt và không yêu cầu điền vào bảng với ngày cụ thể.
ErikE

2
Kho dữ liệu sử dụng rộng rãi các bảng lịch. Các tháng, quý, năm được tính toán trước, cung cấp cho người dùng cuối các trường mà họ có thể lọc / tổng hợp.
David Rushton

Câu trả lời:


694

Sử dụng DATENAMEhoặc DATEPART:

SELECT DATENAME(dw,GETDATE()) -- Friday
SELECT DATEPART(dw,GETDATE()) -- 6

Thx, tôi đã thử tên dữ liệu nhưng sử dụng d, trả lại cho tôi một số nguyên. dw hoạt động như mong đợi

39
Đó là lý do tại sao tôi thích sử dụng tên dữ liệu chọn (ngày trong tuần, getdate ()). Tôi không cần phải nhớ rằng dw trả lại ngày trong tuần .... khi tôi có thể sử dụng "ngày trong tuần".
George Mastros

9
bất cứ ai liếc qua điều này - lưu ý rằng bắt đầu mặc định của tuần là chủ nhật . Hãy xem câu trả lời của @ Sung để biết cách thay đổi điều đó một cách an toàn
JonnyRaa

2
@niico đó là vì SQL lập chỉ mục từ 1 trong khi C thích chỉ mục ngôn ngữ từ 0.
user824276 17/03/18

95

Mặc dù câu trả lời của SQLMenace đã được chấp nhận, có một SETtùy chọn quan trọng bạn nên biết

THIẾT LẬP NGÀY

DATENAME sẽ trả về tên ngày chính xác nhưng không phải cùng giá trị DATEPART nếu ngày đầu tuần đã được thay đổi như minh họa bên dưới.

declare @DefaultDateFirst int
set @DefaultDateFirst = @@datefirst
--; 7 First day of week is "Sunday" by default
select  [@DefaultDateFirst] = @DefaultDateFirst 

set datefirst @DefaultDateFirst
select datename(dw,getdate()) -- Saturday
select datepart(dw,getdate()) -- 7

--; Set the first day of week to * TUESDAY * 
--; (some people start their week on Tuesdays...)
set datefirst 2
select datename(dw,getdate()) -- Saturday
--; Returns 5 because Saturday is the 5th day since Tuesday.
--; Tue 1, Wed 2, Th 3, Fri 4, Sat 5
select datepart(dw,getdate()) -- 5 <-- It's not 7!
set datefirst @DefaultDateFirst

33
Vì vậy, để có được giá trị ngày tháng không đổi, bạn làm ( @@datefirst - 1 + datepart(weekday, thedate) ) % 7. Chủ nhật sẽ luôn là con số không.
Endy Tjahjono

1
Thật kinh khủng khi công cụ này là tĩnh nên bạn phải theo dõi truy vấn gốc, thay đổi giá trị, chạy truy vấn, đặt lại mẫu ban đầu
JonnyRaa

2
Phần hài hước của việc này là NET của DayOfWeekliệt kê có DayOfWeek.Sundayvới giá trị ... 0. Vì vậy, bất kể điều gì DateFirstđược giải quyết, một giá trị trả về SQL không được xử lýWEEKDAY sẽ không bao giờ tương thích với đối tác .NET. Yay, Microsoft.
Eric Wu

26
SELECT  CASE DATEPART(WEEKDAY,GETDATE())  
    WHEN 1 THEN 'SUNDAY' 
    WHEN 2 THEN 'MONDAY' 
    WHEN 3 THEN 'TUESDAY' 
    WHEN 4 THEN 'WEDNESDAY' 
    WHEN 5 THEN 'THURSDAY' 
    WHEN 6 THEN 'FRIDAY' 
    WHEN 7 THEN 'SATURDAY' 
END

26
Bạn nên biết rằng có một chức năng được xây dựng để đạt được điều tương tự. select datename(dw,getdate())
Soham Dasgupta

10
@SohamDasgupta hàm dựng sẵn này không trả về kết quả tương tự cho phiên bản MS SQL không phải tiếng Anh.
Ông Scapegrace

12

Để có được giá trị xác định cho ngày trong tuần cho một ngày nhất định, bạn có thể sử dụng kết hợp giữa DATEPART ()@@ datefirst . Nếu không, bạn phụ thuộc vào các cài đặt trên máy chủ.

Kiểm tra trang web sau để có giải pháp tốt hơn: MS SQL: Ngày trong tuần

Ngày trong tuần sau đó sẽ nằm trong phạm vi 0 đến 6, trong đó 0 là Chủ nhật, 1 là Thứ Hai, v.v. Sau đó, bạn có thể sử dụng một câu lệnh tình huống đơn giản để trả về tên ngày trong tuần chính xác.


5
Vui lòng đặt câu trả lời vào câu trả lời để mọi người không phải nhấp vào liên kết để truy cập.
Martin Smith

11

CHÂU ÂU:

declare @d datetime;
set @d=getdate();
set @dow=((datepart(dw,@d) + @@DATEFIRST-2) % 7+1);

2
Vui lòng bao gồm giải thích về những gì mã của bạn làm và cách nó trả lời câu hỏi. Nếu bạn nhận được một đoạn mã làm câu trả lời, bạn có thể không biết phải làm gì với nó. Trả lời nên cung cấp cho OP và khách truy cập trong tương lai hướng dẫn cách gỡ lỗi và khắc phục sự cố của họ. Chỉ ra, ý tưởng đằng sau mã của bạn là gì, giúp ích rất nhiều trong việc hiểu vấn đề và áp dụng hoặc sửa đổi giải pháp của bạn.
Palec

6

Với SQL Server 2012 trở đi, bạn có thể sử dụng FORMATchức năng

SELECT FORMAT(GETDATE(), 'dddd')

3

đây là bản sao làm việc của mã của tôi, hãy kiểm tra nó, làm thế nào để lấy lại tên ngày từ ngày trong sql

CREATE Procedure [dbo].[proc_GetProjectDeploymentTimeSheetData] 
@FromDate date,
@ToDate date

As 
Begin
select p.ProjectName + ' ( ' + st.Time +' '+'-'+' '+et.Time +' )' as ProjectDeatils,
datename(dw,pts.StartDate) as 'Day'
from 
ProjectTimeSheet pts 
join Projects p on pts.ProjectID=p.ID 
join Timing st on pts.StartTimingId=st.Id
join Timing et on pts.EndTimingId=et.Id
where pts.StartDate >= @FromDate
and pts.StartDate <= @ToDate
END

1

Nếu bạn không muốn phụ thuộc @@DATEFIRSThoặc sử dụng DATEPART(weekday, DateColumn), chỉ cần tính toán ngày trong tuần.

Trong tuần thứ hai (Châu Âu) đơn giản nhất là:

SELECT DATEDIFF(day, '17530101', DateColumn) % 7 + 1 AS MondayBasedDay

Đối với tuần chủ nhật (Mỹ) sử dụng:

SELECT DATEDIFF(day, '17530107', DateColumn) % 7 + 1 AS SundayBasedDay

Điều này trả về số ngày trong tuần (1 đến 7) kể từ ngày 1 tháng 1 tương ứng ngày 7, 1753.


1

Bạn có thể sử dụng DATEPART(dw, GETDATE())nhưng lưu ý rằng kết quả sẽ dựa trên @@DATEFIRSTgiá trị cài đặt máy chủ SQL là cài đặt ngày đầu tuần (Ở châu Âu giá trị mặc định 7 là Chủ nhật).

Nếu bạn muốn thay đổi ngày đầu tuần sang giá trị khác, bạn có thể sử dụng SET DATEFIRST nhưng điều này có thể ảnh hưởng đến mọi nơi trong phiên truy vấn mà bạn không muốn.

Cách khác là xác định rõ ràng giá trị ngày đầu tiên của tuần làm tham số và tránh tùy thuộc vào @@DATEFIRSTcài đặt. Bạn có thể sử dụng công thức sau để đạt được điều đó khi cần:

(DATEPART(dw, GETDATE()) + @@DATEFIRST + 6 - @WeekStartDay) % 7 + 1

đâu @WeekStartDaylà ngày đầu tiên trong tuần bạn muốn cho hệ thống của mình (từ 1 đến 7, nghĩa là từ thứ Hai đến Chủ nhật).

Tôi đã gói nó vào chức năng dưới đây để chúng ta có thể tái sử dụng nó một cách dễ dàng:

CREATE FUNCTION [dbo].[GetDayInWeek](@InputDateTime DATETIME, @WeekStartDay INT)
RETURNS INT
AS
BEGIN
    --Note: @WeekStartDay is number from [1 - 7] which is from Monday to Sunday
    RETURN (DATEPART(dw, @InputDateTime) + @@DATEFIRST + 6 - @WeekStartDay) % 7 + 1 
END

Ví dụ sử dụng: GetDayInWeek('2019-02-04 00:00:00', 1)

Nó tương đương với sau (nhưng độc lập với cài đặt DATEFIRST của máy chủ SQL):

SET DATEFIRST 1
DATEPART(dw, '2019-02-04 00:00:00')

0

Bạn có thể tìm thấy phiên bản này hữu ích.

-- Test DATA
select @@datefirst
create table #test (datum datetime)
insert #test values ('2013-01-01')
insert #test values ('2013-01-02')
insert #test values ('2013-01-03')
insert #test values ('2013-01-04')
insert #test values ('2013-01-05')
insert #test values ('2013-01-06')
insert #test values ('2013-01-07')
insert #test values ('2013-01-08')
-- Test DATA

select  Substring('Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun,Mon,Tue,Wed,Thu,Fri,Sat',
        (DATEPART(WEEKDAY,datum)+@@datefirst-1)*4+1,3),Datum
        from #test 

1
Đây là mã obtuse và không đưa ra dấu hiệu gì về những gì nó đang làm hoặc đang cố gắng đạt được
brewmanz
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.