2009-02-21 54 views
61

Tôi có một bảng có chỉ mục (autoincrement) và giá trị số nguyên. Bảng dài hàng triệu hàng.mysql chọn từ n hàng cuối cùng

Làm cách nào để tìm kiếm nếu một số nhất định xuất hiện trong n hàng cuối cùng của bảng hiệu quả nhất?

Trả lời

87

Bắt đầu từ answer do @chaos, nhưng với một vài thay đổi:

  • Bạn nên luôn sử dụng ORDER BY nếu bạn sử dụng LIMIT. Không có thứ tự ngầm được bảo đảm cho một bảng RDBMS. Bạn có thể thường là nhận các hàng theo thứ tự khóa chính, nhưng bạn không thể dựa vào đó, cũng không thể di chuyển được.

  • Nếu bạn đặt hàng theo thứ tự giảm dần, bạn không cần phải biết số hàng trong bảng trước đó.

  • Bạn phải đặt tên tương quan (còn gọi là bí danh bảng) cho bảng có nguồn gốc.

Dưới đây là phiên bản của tôi về truy vấn:

SELECT `id` 
FROM (
    SELECT `id`, `val` 
    FROM `big_table` 
    ORDER BY `id` DESC 
    LIMIT $n 
) AS t 
WHERE t.`val` = $certain_number; 
+1

Tôi sẽ upvote này nhiều lần nếu tôi có thể, tất cả các câu trả lời khác là lỗi. Đây là những gì tôi đã đăng tải. –

+3

Lưu ý rằng câu trả lời từ @chaos mà tôi giới thiệu đã bị xóa. –

+0

Cảm ơn! Làm thế nào nhiều hồ sơ sẽ động cơ phải quét để có được câu trả lời? Nó n? hoặc m = vị trí của val từ đỉnh? – Nir

12

Tận dụng lợi thế của SORT và LIMIT như bạn làm với phân trang. Nếu bạn muốn khối thứ i của hàng, sử dụng OFFSET.

SELECT val FROM big_table 
where val = someval 
ORDER BY id DESC 
LIMIT n; 

Để trả lời Nir: Thao tác sắp xếp không nhất thiết bị phạt, điều này phụ thuộc vào kế hoạch truy vấn. Vì trường hợp sử dụng này rất quan trọng đối với hiệu suất phân trang, có một số tối ưu hóa (xem liên kết ở trên). Điều này đúng trong postgres cũng "ORDER BY ... LIMIT có thể được thực hiện mà không sắp xếp" E.7.1. Last bullet

explain extended select id from items where val = 48 order by id desc limit 10; 
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+ 
| 1 | SIMPLE  | items | const | PRIMARY  | PRIMARY | 4  | const | 1 | Using index | 
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+ 
+0

Bạn không thể sử dụng MAX() hoặc COUNT() trong một mệnh đề WHERE. –

+0

Thay thế mã không chính xác bằng câu lệnh CASE. –

+0

Trường hợp không loại bỏ NULL vì vậy tôi đã xóa hoàn toàn ví dụ đó. –

3

vì nó là autoincrement, đây là quan điểm của tôi:

Select * from tbl 
where certainconditionshere 
and autoincfield >= (select max(autoincfield) from tbl) - $n 
+0

Tôi chỉ thay đổi thứ tự các điều kiện trong mệnh đề WHERE. –

+4

Câu trả lời này giả định các hàng $ n cuối cùng có các giá trị id tiếp giáp. –

12

cuối 5 hàng lấy trong mysql

làm việc Truy vấn này hoàn toàn

SELECT * FROM (SELECT * FROM recharge ORDER BY sno DESC LIMIT 5)sub ORDER BY sno ASC 

hoặc

select sno from(select sno from recharge order by sno desc limit 5) as t where t.sno order by t.sno asc 
+0

Truy vấn hàng đầu hoạt động hoàn hảo trong MySQL. Cảm ơn! – L0j1k

0

Tôi biết điều này có thể là một chút cũ, nhưng hãy thử sử dụng PDO::lastInsertId. Tôi nghĩ rằng nó làm những gì bạn muốn, nhưng bạn sẽ phải viết lại ứng dụng của bạn để sử dụng PDO (mà là an toàn hơn nhiều so với các cuộc tấn công)

14

Có thể là một câu trả lời rất muộn, nhưng điều này là tốt và đơn giản.

select * from table_name order by id desc limit 5 

Truy vấn này sẽ trả về một bộ cuối cùng 5 giá trị (5 dòng cuối cùng) bạn đã chèn vào trong bảng của bạn

+3

Giá trị này cung cấp cái gì? Câu hỏi được trả lời sáu năm trước. Đoạn mã dường như là tập con của các câu trả lời được cung cấp trước đây và đoạn mã đó không giải thích. – jww

+1

@jww cho OP, đây là câu trả lời đúng –

+0

tuyệt vời, đơn giản và chính xác! +1 – gumuruh

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