Truy vấn so sánh ngày tháng trong SQL


83

Tôi có một bảng với các ngày diễn ra trong tháng 11. Tôi đã viết truy vấn này

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
created_date <= '2013-04-12'

Truy vấn này sẽ trả về mọi thứ đã xảy ra trong tháng 11 (tháng 11) vì nó xảy ra trước ngày '2013-04-12' (vào tháng 12)

Nhưng nó chỉ trở về ngày có sẵn mà đã xảy ra trong những ngày ít hơn 04 (2013- 04 -12)

Có thể là nó chỉ so sánh phần ngày? và không phải cả ngày?

Làm thế nào để khắc phục điều này?

Created_date thuộc loại ngày

Định dạng ngày theo mặc định là yyyy-dd-MM


1
Bạn đang so sánh ngày để chuỗi, không vị để ngày
Panagiotis Kanavos

4
Có lẽ nó nghĩ 2013-04-12? là ngày 12 tháng 4? Hoặc có thể created_datelà một chuỗi và không phải là một ngày?
jpw

Nhìn vào Cast & Chuyển đổi trên T-SQL bằng tay và sử dụng chuyển đổi thích hợp cho miền địa phương của bạn
Steve

3
Không cần phải diễn viên nào cả, chỉ cần sử dụng định dạng bất biến '20130412'
Panagiotis Kanavos

1
Sau đó, thay vì gửi một chuỗi có ngày, hãy thử tạo một truy vấn được tham số hóa và chuyển ngày dưới dạng tham số được nhập ngày. BTW bạn đang sử dụng phiên bản SQL Server nào? DATE đã được thêm vào SQL Server 2008.
Panagiotis Kanavos

Câu trả lời:


82

Thay vì '2013-04-12' có ý nghĩa phụ thuộc vào văn hóa địa phương, hãy sử dụng '20130412' được công nhận là định dạng bất biến của văn hóa.

Nếu bạn muốn so sánh với 04 tháng 12 ngày , bạn nên viết '20.131.204'. Nếu bạn muốn so sánh với 12 tháng 4 ngày , bạn nên viết '20.130.412'.

Bài viết Viết câu lệnh SQL giao dịch quốc tế từ tài liệu của SQL Server giải thích cách viết câu lệnh bất biến văn hóa:

Các ứng dụng sử dụng các API khác hoặc tập lệnh Transact-SQL, thủ tục được lưu trữ và trình kích hoạt, nên sử dụng các chuỗi số chưa được phân tách. Ví dụ: yyyymmdd là 19980924.

BIÊN TẬP

Vì bạn đang sử dụng ADO, tùy chọn tốt nhất là tham số hóa truy vấn và chuyển giá trị ngày tháng dưới dạng tham số ngày tháng. Bằng cách này, bạn tránh hoàn toàn vấn đề về định dạng và cũng có được những lợi ích về hiệu suất của các truy vấn được tham số hóa.

CẬP NHẬT

Để sử dụng định dạng ISO 8601 theo nghĩa đen, tất cả các phần tử phải được chỉ định. Trích dẫn từ phần ISO 8601 trong tài liệu của datetime

Để sử dụng định dạng ISO 8601, bạn phải chỉ định từng phần tử trong định dạng. Điều này cũng bao gồm T, dấu hai chấm (:) và dấu chấm (.) Được hiển thị trong định dạng.

... phần của thành phần thứ hai là tùy chọn. Thành phần thời gian được chỉ định ở định dạng 24 giờ.


@andy không chính xác, định dạng ISO8601 bao gồm yếu tố thời gian. Hoặc như các tài liệu nói , To use the ISO 8601 format, you must specify each element in the format. This also includes the T.
Panagiotis Kanavos

1
Xin lỗi vì không rõ ràng, quan điểm của tôi là ISO8601 xác định thứ tự theo cách bạn mô tả: YYYY-MM-DD hoặc viết tắt là YYYYMMDD. Tuy nhiên, như tài liệu cũng nêu rõ: "datetime không tuân thủ ANSI hoặc ISO 8601.". Bản thân ISO sẽ không yêu cầu một phần thời gian.
andy

Những gì bạn tham khảo không thay đổi thực tế rằng YYYY-MM-DDkhông công nhận là tiêu chuẩn ISO 8601. Thời gian phần được yêu cầu. Gọi nó là sự kỳ lạ của T-SQL nếu bạn muốn, hoặc triển khai không đầy đủ. Nó thậm chí có thể là điều này đã được chuyển sang từ Sybase
Panagiotis Kanavos

31

Hãy thử như thế này

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
created_date <= '2013-12-04'

6
Văn hóa định dạng cụ thể. Đó là ngày 12 tháng 4 hay ngày 4 tháng 12? Định dạng được phân tách bằng dấu gạch ngang KHÔNG phải là định dạng quốc tế
Panagiotis Kanavos

1
Vậy điều gì sẽ xảy ra khi bạn cần lưu trữ dữ liệu từ các khách hàng quốc tế? Hay ngày đến từ một trình duyệt web tuân theo văn hóa của người dùng ? Các hướng dẫn tồn tại vì một lý do, và bằng cách đơn giản KHÔNG sử dụng định dạng sai, bạn tránh được tất cả các lỗi
Panagiotis Kanavos

1
@Nithesh Đây sẽ trở lại vào ngày 12 tháng 4
HelpASisterOut

17
@PanagiotisKanavos Định dạng được phân tách bằng dấu gạch ngang định dạng quốc tế kể từ khi ISO 8601 được xuất bản năm 1988. Các định dạng khác không được khuyến khích và chế giễu . Ngay cả bài báo bạn đã đăng, "Viết câu lệnh SQL giao dịch quốc tế" chưa bao giờ xác định 'yyyymmdd' là bất kỳ loại tiêu chuẩn "quốc tế" nào.
Jesse Webb

2
Thêm dấu ngoặc kép vào ngày giải quyết vấn đề này cho tôi. Đã sử dụng định dạng 19/02/2015. Đã thay đổi thành '2/19/2015' và nó bắt đầu hoạt động. Cảm ơn vì ý tưởng đơn giản.
Ethan Turk

9

Nếu Bạn chỉ so sánh với date vale, thì việc chuyển đổi nó thành date (không phải datetime ) sẽ hoạt động

select id,numbers_from,created_date,amount_numbers,SMS_text 
 from Test_Table
 where 
 created_date <= convert(date,'2013-04-12',102)

Việc chuyển đổi này cũng được áp dụng trong quá trình sử dụng ) (getdate chức năng


4

Bạn đặt <=và nó cũng sẽ bắt kịp ngày nhất định. Bạn có thể thay thế nó bằng <chỉ.


2

vui lòng thử với truy vấn dưới đây

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
convert(datetime, convert(varchar(10), created_date, 102))  <= convert(datetime,'2013-04-12')

0

Định dạng ngày là yyyy-mm-dd. Vì vậy, truy vấn trên đang tìm kiếm các bản ghi cũ hơn 12Apr2013

Đề nghị bạn kiểm tra nhanh bằng cách đặt chuỗi ngày thành '2013-04-30', nếu không có lỗi sql, định dạng ngày được xác nhận thành yyyy-mm-dd.


0

Cố gắng sử dụng "#" trước và sau ngày và chắc chắn về định dạng ngày hệ thống của bạn. có thể là "YYYYMMDD O YYYY-MM-DD O MM-DD-YYYY O USING '/ O \'"

Ví dụ:

 select id,numbers_from,created_date,amount_numbers,SMS_text 
 from Test_Table
 where 
 created_date <= #2013-04-12#
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.