2014-09-01 26 views
6

Cách tiếp cận tốt nhất (nhanh nhất) nào để so sánh nếu ngày nằm trong phạm vi ngày tháng độc lập so với năm?Ngày giữa các ngày, bỏ qua năm

bảng "ngày":

some_column| since  | upto  | 
    -----------|--------------|-------------| 
    'foo'  | '2011-05-01' | '2013-06-01'| 

Bây giờ tôi muốn truy vấn này để trở về 'foo'

SELECT foo FROM dates WHERE '2014-05-05' BETWEEN `since` AND `upto` 

Nếu cần, tôi có thể thay đổi loại/định dạng ngày tháng lưu trữ trong "ngày" bảng , nhưng tôi không thể thay đổi định dạng ngày tháng mà tôi đưa vào truy vấn vì giá trị đó thường là từ một bảng khác (Đó là một phần của truy vấn phức tạp hơn khi sử dụng các phép nối).

+0

Hiện nay chúng được lưu trữ trong loại ngày. Tôi chỉ nói rằng nếu cần, tôi có thể thay đổi điều đó. – gadelat

+2

ngày không phải là 'định dạng'. Nó là một loại. –

+0

Ok bạn đã cho tôi. Đó là điều tôi muốn nói. – gadelat

Trả lời

3

Sử dụng DayOfYear chức năng:

SELECT foo FROM dates WHERE DayOfYear('2014-05-05') 
    BETWEEN DayOfYear(`since`) AND DayOfYear(`upto`) 
+0

Ý nghĩ hay. Tôi cũng đã cân nhắc điều đó. Nhưng những năm nhuận sẽ vượt qua nó. Ngày 1 tháng 3 là Ngày 60 trong một năm không phải là năm nhuận, nhưng ngày thứ 61 trên một năm nhuận. –

+0

Nếu MySQL không điều chỉnh cho điều này, thay vào đó là cuộn chức năng kiểu Julianizer của riêng bạn ('MONTH (dt) * 100 + DAY (dt)' nên làm điều đó). –

+0

Nó không rõ ràng đối với tôi làm thế nào để tích hợp julianizer đó vào truy vấn bạn đã đăng, bạn có thể làm rõ không? – gadelat

1

Vì bạn đã cho biết rằng bạn đang lưu trữ một năm tùy ý trong dữ liệu của mình, bạn có thể tiếp tục sử dụng loại DATE. Sau đó, nó chỉ đi xuống để làm thế nào để truy vấn.

  • Lưu trữ các trường sử dụng một năm tùy ý cố định. Bạn nên sử dụng một năm nhuận để phù hợp với khả năng của các giá trị ngày 29 tháng 2. Năm 2000 hoạt động rất tốt. (0004 sẽ không hoạt động vì nó quá nhỏ đối với loại Date của MySQL.)

  • Thay thế năm của bất kỳ giá trị nào bạn đang truy vấn cùng năm đó.

  • Cân nhắc các phạm vi vượt qua cuối một năm và sang năm tiếp theo. Để trả lời đầy đủ điều đó, bạn sẽ cần một câu hỏi như sau:

    SET @dt = cast(CONCAT('2000',RIGHT(thesourcedatevalue,6)) as DATE); 
    
    SELECT some_column FROM dates 
    WHERE (since <= upto AND since <= @dt AND upto >= @dt) OR 
         (since > upto AND (since <= @dt OR upto >= @dt)) 
    

    Here is a SQL Fiddle that demonstrates

  • Đối với hiệu suất, bạn nên chắc chắn rằng có một chỉ số bao gồm các lĩnh vực sinceupto.

+0

a) 0004 không quá nhỏ đối với loại ngày của mysql. b) Nó không hoạt động và tôi thậm chí không thấy nó có thể hoạt động như thế nào. Điều kiện được đính kèm trong cặp ngoặc đơn cuối cùng không có ý nghĩa. Ngoài ra, tôi không thể lưu trữ "@dt" với năm cố định. Nó có thể là năm 2000, có thể là năm 2014, bất kỳ năm nào. Tôi đã nói nhiều lần rằng tôi có thể thay đổi định dạng/loại/năm trong bảng, nhưng không phải là ngày mà chúng so sánh. Tôi đã hy vọng đề xuất của bạn sẽ bao gồm cách thay thế năm "@dt" thành năm 2000 – gadelat

+0

Mỗi [các tài liệu này] (http://dev.mysql.com/doc/refman/5.7/en/datetime.html) Phạm vi được hỗ trợ của loại DATE' là '1000-01-01' đến' 9999-12-31'. –

+0

Dòng thứ hai của câu lệnh WHERE (bao gồm điều kiện cuối cùng trong dấu ngoặc đơn) ở đó để bao gồm trường hợp tôi mô tả, trong đó phạm vi hoạt động từ tháng 12 đến tháng 1, vượt qua ranh giới năm. Nếu bạn không có trường hợp như vậy, bạn có thể xóa toàn bộ dòng đó. –

2
SELECT foo FROM dates WHERE DATE_FORMAT('2014-01-15', "%m-%d") 
    BETWEEN DATE_FORMAT(`since`,"%m-%d") AND DATE_FORMAT(`upto`,"%m-%d") 

Đây là bản demo SQL FIDDLE

Các vấn đề liên quan