2009-08-20 40 views
6

Tôi có một bảng trong cơ sở dữ liệu MySQL mà từ đó tôi muốn chọn hàng có dấu thời gian gần nhất với một dấu thời gian nhất định.Cách hiệu quả nhất để tìm số nguyên gần nhất trong MySQL?

time là cột dấu thời gian (dấu thời gian UNIX số nguyên). Tôi đã chọn 1250710000 tùy ý.

Đây là câu hỏi mà tôi đã đưa ra, và tôi tự hỏi nếu có một cách hiệu quả hơn để làm điều đó:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table 
ORDER BY time_dist ASC LIMIT 1 

Đây có phải là cách tốt nhất để làm điều đó?

Trả lời

10

Giả sử time được lập chỉ mục, bạn có thể lấy kỷ lục tiếp theo gần miễn phí:

SELECT * FROM table WHERE time > 1250710000 ORDER BY time LIMIT 1 

Và nếu tôi không sai, cùng nên áp dụng đối với kỷ lục trước đó, MySQL sẽ chỉ đọc chỉ số theo thứ tự ngược lại. Sử dụng một ĐOÀN của hai người, ra lệnh cho họ theo ngày khác biệt và thì đấy! Kết quả sẽ giống như thế này

SELECT * 
FROM 
(
    (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time > 1250710000 ORDER BY time ASC LIMIT 1) 
    UNION ALL 
    (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time < 1250710000 ORDER BY time DESC LIMIT 1) 
) AS tmp 
ORDER BY time_diff 
LIMIT 1 

Lý tưởng nhất, thay vì >< bạn nên sử dụng >=<= và loại trừ các hồ sơ tài liệu tham khảo sử dụng id chính của nó, để giải thích cho các hồ sơ chia sẻ dấu thời gian tương tự.

+0

Chết tiệt! Tôi vừa mới gõ chính xác điều đó! – NickZoic

+0

Ý tưởng tuyệt vời, nhưng dấu thời gian tham chiếu ('1250710000' trong trường hợp này) không nằm trong cùng một bảng. Có nói rằng, tôi cho rằng truy vấn này là về cùng về hiệu quả? – heyitsme

+0

** @ cyouung: ** Truy vấn này không giống nhau về hiệu quả. Truy vấn của bạn thực hiện 'ABS (thời gian - 125071000)' trên * mọi hàng đơn *. Miễn là bạn có chỉ mục trên 'thời gian', truy vấn này sẽ không bao giờ đọc nhiều hơn hai hàng. –

1

Như Evan đã nói, cách bạn có nó là tốt. Tôi muốn giới thiệu một chỉ mục trên trường dấu thời gian đó, để MySQL có thể quét chỉ mục nhỏ hơn là toàn bộ bảng. Ngoài ra, tôi sẽ thử một số 'quyền anh' để xem liệu chỉ số có thể tăng tốc độ không:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table 
WHERE time between(1250610000,1250810000) 
ORDER BY time_dist ASC LIMIT 1 

Giới hạn trên để truy vấn khoảng +/- 1 ngày. Bạn sẽ phải thực hiện một số điểm chuẩn để xem liệu quét chỉ mục bổ sung (mệnh đề where) có nhanh hơn tính toán ABS() trên tất cả các mục trong bảng hay không.

+0

Tôi không thích có giới hạn tùy ý như vậy. –

1

Sẽ hiệu quả hơn khi chọn thời gian tối thiểu lớn hơn và thời gian tối thiểu là sau đó chỉ nhỏ hơn hai lần. Điều đó sẽ tránh phải hoạt động trên bảng toàn bộ .

CHỌN MAX (thời gian) AS prev WHERE time < 1250710000;

CHỌN MIN (thời gian) AS next WHERE time> 1250710000;

CHỌN MIN (ABS (trước), ABS (tiếp theo));

SQL của tôi không đủ mạnh để kết hợp chúng thành một và chi phí của ba truy vấn có thể giết bất kỳ khoản tiết kiệm nào, nhưng có thể là có thể.

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