2015-06-10 21 views
9

Tôi có một bảng MySQL DB với nhiều trường loại ngày tháng. Tôi cần phải thực hiện các truy vấn SELECT khác nhau trên bảng này nhưng tôi không chắc chắn cách nào là tốt nhất để tìm các bản ghi từ cùng một tháng.Truy vấn SELECT hiệu quả để tìm các bản ghi trong một tháng

Tôi biết tôi có thể làm như sau:

SELECT * 
    FROM table 
WHERE MONTH(somedate) = 5 
    AND YEAR(somedate) = 2015 

Nhưng tôi tiếp tục đọc đó không phải là hiệu quả và rằng tôi nên đi với việc sử dụng ngày thực tế, tức là

SELECT * 
    FROM table 
WHERE somedate BETWEEN '2015-05-01' AND '2015-05-31' 

Tuy nhiên, tất cả tôi sẽ có là tháng và năm là các biến đến từ PHP. Làm cách nào để tính toán ngày cuối cùng của tháng một cách dễ dàng và nhanh chóng nếu tôi đi với lựa chọn thứ hai?

+0

Tôi đang tìm 'between' chậm hơn' month/year' và 'like', trên db của tôi. Tháng/năm = 'Hiển thị các hàng 0 - 29 (tổng cộng 77, Truy vấn mất 0.0825 giây)'. Giữa = 'Hiển thị các hàng 0 - 29 (tổng cộng 77, Truy vấn mất 0,1059 giây)'. Giống như = 'Hiển thị các hàng 0 - 29 (tổng cộng 77, Truy vấn mất 0,0815 giây)'. Đây là trên một bảng hàng 7k. Chủ đề này chỉ theo hướng khác. http://dba.stackexchange.com/questions/96245/mysql-date-field-filter-by-like-vs-month – chris85

+0

MySQL có thể sử dụng hiệu quả chỉ mục có cột hàng đầu là 'somedate'. Nếu bạn không có chỉ mục như vậy, thì bạn có thể tạo một chỉ mục, ví dụ: 'CREATE INDEX ON table (somedate)'. Miễn là truy vấn trả về dưới 10% số hàng trong bảng, chỉ mục sẽ làm cho truy vấn nhanh hơn nhiều. Với các hàm bao quanh cột somedate, MySQL phải đánh giá các hàm đó trên mọi hàng trong bảng. – spencer7593

+0

Sử dụng 'GIẢI THÍCH 'để xem kế hoạch thực hiện. Để so sánh hiệu suất, hãy đảm bảo rằng kết quả truy vấn không được trả về từ bộ nhớ truy vấn. Có một số cách để thực hiện điều đó, ví dụ: 'SQL_NO_CACHE' hit, bao gồm biến do người dùng định nghĩa trong truy vấn, vô hiệu hóa bộ đệm truy vấn, v.v. (Chúng tôi thực sự có các máy chủ MySQL của chúng tôi được cấu hình để lưu trữ * chỉ * truy vấn có chứa gợi ý' SQL_CACHE' , vì vậy chúng tôi kiểm soát những truy vấn nào có thể được lưu trong bộ nhớ cache và ngăn các kết quả bị xóa bởi các truy vấn mà chúng tôi không cần lưu trữ.) – spencer7593

Trả lời

9

Đừng tính toán ngày cuối cùng của tháng. Thay vào đó, hãy tính ngày đầu tiên của tháng tiếp theo.

truy vấn của bạn có thể như thế này

WHERE t.mydatetimecol >= '2015-05-01' 
    AND t.mydatetimecol < '2015-05-01' + INTERVAL 1 MONTH 

Lưu ý rằng chúng tôi đang làm một ít hơn so sánh, không phải là một "nhỏ hơn hoặc bằng" ... đây là rất thuận tiện cho việc so sánh dấu thời gian và Các cột DATETIME, có thể bao gồm một phần thời gian.

Lưu ý rằng so sánh BETWEEN là "nhỏ hơn hoặc bằng". Để có được một sự so sánh tương đương với các truy vấn trên, chúng ta cần phải làm

WHERE t.mydatetimecol 
     BETWEEN '2015-05-01' AND '2015-05-01' + INTERVAL 1 MONTH + INTERVAL -1 SECOND 

(này giả định rằng độ phân giải của DATETIMETIMESTAMP là xuống đến một giây. Trong cơ sở dữ liệu khác, chẳng hạn như SQL Server, độ phân giải là tốt hơn một giây, vì vậy chúng tôi sẽ có tiềm năng thiếu một hàng có giá trị '2015-05-31 23: 59: 59.997'. Chúng tôi không gặp vấn đề như vậy với ít hơn ngày đầu tiên của tháng tiếp theo so sánh ... < '2015-06-01'

Không cần phải tự mình thực hiện phép tính tháng hoặc ngày, hãy để MySQL làm điều đó cho bạn. Nếu bạn bỏ thêm 1 tháng, bạn phải xử lý số rollover từ tháng 12 tới Tháng 1 và vô tận t năm. MySQL có tất cả những gì đã được xây dựng sẵn.

+0

Spencer công việc tuyệt vời – AsConfused

3

date('t', strtotime("$year-$month-01")) sẽ cho ngày trong tháng

+2

Đó là câu hỏi về hiệu suất, không phải là cách đặt câu hỏi .. – chris85

+0

Câu hỏi "cách thực hiện" cho tác vụ cụ thể này đã được hỏi ở cuối. Tôi nghĩ rằng GIỮA sẽ là một người biểu diễn tốt hơn, và có thể giải thích thêm về điều đó sau này nếu ai đó không nhận được nó trước. –

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