2011-02-01 33 views
8

Tôi có một bảng có tên là products trong cơ sở dữ liệu MySQL. products trông giống như sau:SQL: Tìm hàng tiếp theo trong mệnh đề where được cấp ID

id name  din  strength active deleted 
1 APA TEST 00246374 25  1  0 
4 APA BOB 00246375 50  1  0 
5 APA TIRE 00246888 50  1  0 
7 APA ROT 00521414 100  1  0 
9 APA APA 01142124 100  1  0 
6 APA CODE 00121212 150  1  0 
8 APA SERV 00011145 600  1  0 

Rõ ràng tôi đã bỏ qua một số cột không quan trọng đối với câu hỏi của mình. Khi tôi truy vấn bảng này, tôi sẽ sắp xếp theo một trong các cột khác nhau (Giao diện người dùng cho phép người dùng cá nhân thay đổi cột sắp xếp và thứ tự) và tôi có thể có một mệnh đề tìm kiếm trong trường hợp này tôi sẽ thực hiện mệnh đề LIKE trên NAME và DIN.

Điều tôi muốn biết là cung cấp thông tin sắp xếp và thông tin tìm kiếm và ID của một sản phẩm cụ thể (Giả sử tôi đã tìm kiếm 004, trả về 3 kết quả và tôi đang xem một trong số các kết quả đó) nhận các sản phẩm tiếp theo và trước đó?

Tôi cần làm điều này, bởi vì nếu người dùng nhấp để chỉnh sửa/xem một trong các sản phẩm sau khi tìm kiếm và sắp xếp kết quả, họ muốn có thể chuyển qua kết quả mà không cần truy cập trang trước.

Có cách nào tốt và hiệu quả để thực hiện việc này trong SQL hay không, tôi có sử dụng PHP tốt nhất không? Bất kỳ ý tưởng cũng được chào đón.

Hiện đang sử dụng truy vấn SQL này, được gặp các vấn đề nếu tôi sắp xếp theo cột strength như có giá trị nhân bản

SELECT T.* 
FROM `wp_products` T 
INNER JOIN `wp_products` curr on curr.id = 38 
    AND ((T.strength = curr.strength and T.id < curr.id) 
    OR (T.strength > curr.strength)) 
WHERE T.active = 1 AND T.deleted = 0 AND (T.name LIKE '%%' OR T.din LIKE '%%') 
ORDER BY T.strength ASC, T.id ASC 
LIMIT 1 

mã PHP của tôi (sử dụng WordPress) (Được thiết kế để có được những mục tiếp theo)

$sql = 'SELECT T.* 
FROM `' . $wpdb->prefix . 'apsi_products` T 
INNER JOIN `' . $wpdb->prefix . 'apsi_products` curr on curr.id = ' . $item->id . ' 
    AND ((T.' . $wpdb->escape($query['orderby']) . ' = curr.' . $wpdb->escape($query['orderby']) . ' and T.id > curr.id) 
    OR (T.' . $wpdb->escape($query['orderby']) . ' > curr.' . $wpdb->escape($query['orderby']) . ')) 
WHERE T.active = 1 AND T.deleted = 0 AND (T.name LIKE \'%' . $query['where'] . '%\' OR T.din LIKE \'%' . $query['where'] . '%\') 
ORDER BY T.' . $wpdb->escape($query['orderby']) . ' ' . $query['order'] . ', T.id ASC 
LIMIT 1;'; 

Trả lời

5

Bạn cần có tham chiếu đến bản ghi hiện tại và sau đó dần tìm kiếm bản ghi tiếp theo dựa trên các cột được sắp xếp. Ví dụ dưới đây giả định nó được sắp xếp trên

ORDER BY Active, DIN, NAME 

Đầu tiên:

SELECT * 
FROM TABLE 
WHERE NAME LIKE '%X%' AND DIN LIKE '%%' 
ORDER BY Active, DIN, Name 
LIMIT 1; 

Tiếp theo: (chắc chắn rằng bạn tách CURR.ID = 6 và AND-ORS với dấu ngoặc đúng!)

SELECT * 
FROM TABLE T 
INNER JOIN TABLE CURR ON CURR.ID = 6 # the current ID being viewed 
    AND ((T.Active = Curr.Active AND T.DIN = Curr.DIN AND T.NAME > Curr.Name) 
    OR (T.Active = Curr.Active AND T.DIN > Curr.DIN) 
    OR T.Active > Curr.Active) 
WHERE T.NAME LIKE '%X%' AND T.DIN LIKE '%%' 
ORDER BY T.Active, T.DIN, T.Name 
LIMIT 1; 

Mẫu làm việc được trình bày bên dưới

create table products 
(ID int, SEED int, NAME varchar(20), DIN varchar(10), ACTIVE int, DELETED int); 
insert products values 
(1, 0, 'Product #1', '004812', 1, 0), 
(2, 0, 'Product #2', '004942', 0, 0), 
(3, 0, 'Product #3', '004966', 1, 0), 
(4, 0, 'Product #4', '007437', 1, 1), 
(5, 2, 'Product #2', '004944', 0, 0), 
(6, 2, 'Product #2', '004944', 1, 0); 

SELECT * 
FROM products 
WHERE active = 1 AND deleted = 0 
ORDER BY din DESC, ID desc; 

Output: 
"ID";"SEED";"NAME";"DIN";"ACTIVE";"DELETED" 
"3";"0";"Product #3";"004966";"1";"0" 
"6";"2";"Product #2";"004944";"1";"0" 
"1";"0";"Product #1";"004812";"1";"0" 

Nếu hiện nay là hàng với ID = 6, hồ sơ tiếp theo có thể được lấy ra sử dụng

SELECT T.* 
FROM products T 
INNER JOIN products curr on curr.ID = 6 
    AND ((T.din = curr.din and T.ID > curr.ID) 
    OR (T.din < curr.din)) 
WHERE T.active = 1 AND T.deleted = 0 
ORDER BY T.din DESC, T.ID ASC 
LIMIT 1; 
+0

Xin lỗi, tôi đã luôn luôn là khủng khiếp với SQL. Tôi có nên để nguyên tham chiếu đến CURR như hiện tại hay tôi nên thay đổi CURR và TABLE thành tên bảng của mình? –

+0

BẢNG là trình giữ chỗ cho tên bảng của bạn. CURR và T là bí danh - để chúng một mình. – RichardTheKiwi

+0

Tôi không thành công nếu không có truy vấn của bạn, nhiều khả năng tôi đang làm điều gì sai. Truy vấn của tôi trông như thế này: 'SELECT * FROM table_name WHERE active = 1 AND deleted = 0 ORDER BY din DESC' và khi tôi chạy truy vấn của bạn, tôi nhận được hàng đầu tiên được trả về bởi truy vấn của tôi mặc dù tôi đang sử dụng ID thứ 5 đã được trả lại . Tôi sẽ lấy ID 38 từ ID thứ 6. Ý tưởng? –

0

Câu hỏi thú vị. Tôi không nghĩ rằng bạn có thể làm điều đó trong một truy vấn, nhưng bạn có thể kéo nó ra có lẽ với ba.

Truy vấn đầu tiên kéo hàng trả lời. Bí quyết sẽ là giữ giá trị cho cột mà họ đã sắp xếp. Giả sử đây là "SortedColumn" và giá trị là "M". Giả sử id của hàng bạn nhận được là 10.

Truy vấn thứ hai của bạn sẽ giống như truy vấn thứ nhất, nhưng sẽ là "đầu 1" và sẽ thêm vào mệnh đề where "... and sortedColumn> = ' M 'và id <> 10 "Điều này giúp bạn có được hàng tiếp theo. Bạn có thể muốn trả lại 10 hàng và giữ cho chúng để tránh làm điều này hơn và hơn.

Để nhận trước đó, hãy chuyển thứ tự của bạn thành giảm dần và mệnh đề where bạn thêm là "... và sortColumn < = 'M' và id <> 10". Điều này giúp bạn có được hàng trước đó. Một lần nữa, 10 hàng có thể hữu ích hơn cho người dùng của bạn.

Hy vọng điều này sẽ hữu ích.

+0

Nó có thể được thực hiện trong một truy vấn. Xem câu trả lời của tôi – RichardTheKiwi

+0

Tôi đã thử điều này một cách nhanh chóng Tôi không tin rằng nó có thể hoạt động. Giả sử tôi sắp xếp theo cột tên. Ví dụ, phần 'name'> = 'PRODUCT NAME # 3' dường như không hoạt động –

+0

@cyberwiki: tốt. –

1

Nếu không có lớp bộ nhớ cache bền vững như memcached, nơi bạn có thể lưu trữ kết quả và nhận được kết quả mà không cần truy vấn lại, một giải pháp đơn giản có thể cho phép query cache trong mysql. Bằng cách này, nếu bộ nhớ cache không hết hiệu lực từ querys khác, khi bạn gửi lại truy vấn chi phí kéo kết quả sẽ được hạ xuống

+0

nó có thể được thực hiện hiệu quả chỉ bằng một truy vấn. Xem câu trả lời của tôi – RichardTheKiwi

+0

@cyberwiki từ những gì tôi hiểu từ câu hỏi, nó không phải là một vấn đề truy vấn duy nhất, vì các mục sẽ được yêu cầu từ các trang khác nhau. Truy vấn của bạn sẽ giải quyết cách truy vấn cho các mục khác nhau, nhưng sẽ được đánh giá lại cho mỗi yêu cầu trang, bạn có đồng ý không? – Ass3mbler

+0

Có, nhưng với chỉ mục thích hợp, mỗi giới hạn 1 chỉ lấy 1 bản ghi theo yêu cầu, hiệu quả. Mỗi lần tải trang SO yêu cầu khoảng 10 mục ít nhất là từ db, do đó, các chuyến đi khứ hồi nên là một mối quan tâm nhỏ. – RichardTheKiwi

1

Đối với mỗi hiển thị kết quả, thiết lập các tiếp theotrước liên kết với ID thích hợp.

Không thể thay đổi thứ tự sắp xếp từ chế độ xem chi tiết.

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