Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Giải pháp cho DATEDIFF () Bỏ qua SET DATEFIRST trong SQL Server (Ví dụ T-SQL)

Một điều thú vị về DATEDIFF() trong SQL Server là nó bỏ qua SET DATEFIRST của bạn giá trị.

Tuy nhiên, đây không phải là một lỗi. Tài liệu của Microsoft cho DATEDIFF() nêu rõ những điều sau:

Chỉ định SET DATEFIRST không ảnh hưởng đến DATEDIFF . DATEDIFF luôn sử dụng Chủ nhật là ngày đầu tiên trong tuần để đảm bảo chức năng hoạt động một cách xác định.

Trong trường hợp bạn không biết, hãy SET DATEFIRST đặt ngày đầu tiên trong tuần cho phiên của bạn. Đó là một số từ 1 đến 7 (tương ứng với Thứ Hai đến Chủ Nhật).

Giá trị ban đầu cho SET DATEFIRST được đặt ngầm bởi cài đặt ngôn ngữ (mà bạn có thể đặt bằng SET LANGUAGE tuyên bố). Giá trị thực tế sẽ phụ thuộc vào ngôn ngữ được đặt. Ví dụ:giá trị mặc định cho us_english ngôn ngữ là 7 (Chủ nhật), trong khi mặc định cho British ngôn ngữ là 1 (Thứ hai).

Tuy nhiên, bạn có thể sử dụng SET DATEFIRST để ghi đè câu lệnh này để bạn có thể tiếp tục sử dụng cùng một ngôn ngữ trong khi sử dụng một ngày khác trong ngày đầu tuần.

Nhưng như đã đề cập, SET DATEFIRST giá trị không ảnh hưởng đến DATEDIFF() hàm số. DATEDIFF() hàm luôn giả định rằng Chủ nhật là ngày đầu tiên trong tuần bất kể SET DATEFIRST của bạn là gì giá trị.

Điều này có thể gây ra một số sự cố thú vị khi sử dụng DATEDIFF() nếu bạn không biết nó hoạt động như thế nào.

Nếu bạn thấy mình trong tình huống này, hy vọng các ví dụ trên trang này có thể giúp ích.

Ví dụ 1 - Vấn đề

Đầu tiên, đây là một ví dụ về vấn đề thực tế. Lưu ý rằng chúng tôi có thể truy xuất SET DATEFIRST giá trị bằng cách chọn @@DATEFIRST .

 DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06'; ĐẶT NGÔN NGỮ us_english; CHỌN @@ DATEFIRST NHƯ 'ĐẶT Giá trị DATEFIRST', DATEDIFF (tuần, @startdate, @enddate) NHƯ 'us_english DATEDIFF () Kết quả'; ĐẶT NGÔN NGỮ Tiếng Anh; CHỌN @@ DATEFIRST NHƯ 'Đặt giá trị DATEFIRST', DATEDIFF (tuần, @startdate, @enddate) NHƯ 'Tiếng Anh DATEDIFF () Kết quả'; 

Kết quả:

 + ----------------------- + ---------------------- ---------- + | ĐẶT giá trị DATEFIRST | us_english DATEDIFF () Kết quả || ----------------------- + ------------------- ------------- || 7 | 0 | + ----------------------- + ----------------------- --------- ++ ----------------------- + --------------- -------------- + | ĐẶT giá trị DATEFIRST | DATEDIFF của Anh () Kết quả || ----------------------- + ------------------- ---------- || 1 | 0 | + ----------------------- + ----------------------- ------ + 

Trong trường hợp này, ngày đầu tiên rơi vào Chủ nhật và ngày thứ hai rơi vào Thứ Hai. Do đó, bạn thường mong đợi DATEDIFF() của Anh kết quả trả về 1 . Bạn sẽ mong đợi điều này vì ranh giới phần trong tuần bị vượt qua khi nó đi từ Chủ Nhật đến Thứ Hai (vì SET DATEFIRST giá trị là 1 có nghĩa là “Thứ Hai” và Thứ Hai đánh dấu sự bắt đầu của một tuần mới).

Nhưng vì DATEDIFF() bỏ qua SET DATEFIRST của bạn giá trị và giả định rằng Chủ nhật là ngày bắt đầu của tuần, chúng tôi nhận được cùng một kết quả cho cả hai ngôn ngữ.

Để chắc chắn, tôi sẽ chạy lại truy vấn, nhưng lần này tôi sẽ đặt SET DATEFIRST giá trị rõ ràng . Nói cách khác, thay vì đặt ngôn ngữ, tôi sẽ sử dụng SET DATEFIRST tuyên bố:

 DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06'; SET DATEFIRST 7; SELECT @@ DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF (tuần, @startdate, @enddate) AS 'us_english DATEDIFF () Result'; SET DATEFIRST 1; SELECT @@ DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF (week, @startdate, @enddate) AS 'British DATEDIFF () Result'; 

Kết quả:

 + ----------------------- + ---------------------- ---------- + | ĐẶT giá trị DATEFIRST | us_english DATEDIFF () Kết quả || ----------------------- + ------------------- ------------- || 7 | 0 | + ----------------------- + ----------------------- --------- ++ ----------------------- + --------------- -------------- + | ĐẶT giá trị DATEFIRST | DATEDIFF của Anh () Kết quả || ----------------------- + ------------------- ---------- || 1 | 0 | + ----------------------- + ----------------------- ------ + 

Cùng một kết quả, ngay cả khi bạn đặt SET DATEFIRST một cách rõ ràng giá trị. Tuy nhiên, điều này không có gì ngạc nhiên - tôi sẽ ngạc nhiên nếu điều đó không trả về cùng một kết quả.

Ngoài ra, điều này chỉ xác nhận rằng DATEDIFF() đang hoạt động chính xác như dự định.

Vì vậy, làm cách nào để chúng tôi thay đổi nó để DATEDIFF() của chúng tôi kết quả tôn vinh SET DATEFIRST của chúng tôi giá trị?

Giải pháp

Dưới đây là một giải pháp / cách giải quyết sẽ cho phép bạn đạt được kết quả như mong đợi. Điều này sẽ đảm bảo rằng SET DATEFIRST của bạn cài đặt được tính vào DATEDIFF() của bạn các kết quả.

Tất cả những gì bạn cần làm là trừ đi @@DATEFIRST từ ngày nhập.

 DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06'; SET DATEFIRST 7; SELECT @@ DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF (tuần, DATEADD (ngày , example @ sqldat.com @ DATEFIRST, @startdate), DATEADD (day, example @ sqldat.com @ DATEFIRST, @enddate)) AS 'us_english DATEDIFF () Result'; SET DATEFIRST 1; SELECT @@ DATEFIRST AS 'SET DATEFIRST Giá trị ', DATEDIFF (tuần, DATEADD (ngày, example @ sqldat.com @ DATEFIRST, @startdate), DATEADD (ngày, example @ sqldat.com @ DATEFIRST, @enddate)) NHƯ' Kết quả DATEDIFF () của Anh ';  

Kết quả:

 + ----------------------- + ---------------------- ---------- + | ĐẶT giá trị DATEFIRST | us_english DATEDIFF () Kết quả || ----------------------- + ------------------- ------------- || 7 | 0 | + ----------------------- + ----------------------- --------- ++ ----------------------- + --------------- -------------- + | ĐẶT giá trị DATEFIRST | DATEDIFF của Anh () Kết quả || ----------------------- + ------------------- ---------- || 1 | 1 | + ----------------------- + ----------------------- ------ + 

Điều này sử dụng DATEADD() chức năng để giảm số lượng ngày nhập @@DATEFIRST (là SET DATEFIRST của bạn giá trị).

Trong trường hợp này, DATEDIFF() hàm vẫn sử dụng Chủ nhật là ngày đầu tiên của tuần, tuy nhiên, các ngày thực tế được sử dụng trong phép tính là khác nhau. Chúng đã được chuyển ngược thời gian theo số tiền @@DATEFIRST .

Ví dụ sau đây cho thấy các ngày được sử dụng trong phép tính:

 DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06'; SET DATEFIRST 7; SELECT @startdate AS 'Original Date', @@ DATEFIRST AS 'Subtract By', DATEADD (day, example @ sqldat.com @ DATEFIRST, @startdate) AS 'Ngày kết quả'UNION ALLSELECT @enddate, @@ DATEFIRST, DATEADD (day, example @ sqldat.com @ DATEFIRST, @enddate); ĐẶT DATEFIRST 1; CHỌN @startdate làm 'Ngày gốc', @@ DATEFIRST làm 'Trừ đi', DATEADD (ngày, ví dụ @ sqldat.com @ DATEFIRST, @startdate) Làm 'Ngày kết quả'UNION ALLSELECT @enddate, @@ DATEFIRST , DATEADD (ngày, ví dụ @ sqldat.com @ DATEFIRST, @enddate); 

Kết quả:

 + ----------------- + --------------- + ------------ ------ + | Ngày gốc | Trừ đi bằng | Ngày kết quả || ----------------- + --------------- + ------------ ------ || Năm 2025-01-05 | 7 | 2024-12-29 || Năm 2025-01-06 | 7 | 2024-12-30 | + ----------------- + --------------- + --------- --------- ++ ----------------- + --------------- + ----- ------------- + | Ngày gốc | Trừ đi bằng | Ngày kết quả || ----------------- + --------------- + ------------ ------ || Năm 2025-01-05 | 1 | Năm 2025-01-04 || Năm 2025-01-06 | 1 | 2025-01-05 | + ----------------- + --------------- + --------- --------- + 

Vì vậy, trong giải pháp của chúng tôi, DATEDIFF() đã sử dụng "Ngày kết quả" trong các tính toán của nó.

Nếu bạn đang gặp sự cố với DATEDIFF() bỏ qua SET DATEFIRST , hy vọng bài viết này hữu ích.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách cài đặt SQL Server trên Ubuntu 18.04

  2. So sánh ngày tháng trong T-SQL, bỏ qua phần thời gian

  3. Cách bật Tất cả Ràng buộc Kiểm tra &Khóa ngoại cho Bảng trong SQL Server (Ví dụ T-SQL)

  4. Làm thế nào để xử lý vệ sinh thoát khỏi các dấu ngoặc kép có thể bị đánh bại bởi SQL injection trong SQL Server?

  5. Cách phân tích hoạt động của một cơ sở dữ liệu trong SQL Server