2009-03-23 23 views
7

Tôi có một bảng cơ sở dữ liệu MySQL với cấu trúc này:tìm nạp danh sách liên kết trong cơ sở dữ liệu MySQL

table 
    id INT NOT NULL PRIMARY KEY 
    data .. 
    next_id INT NULL 

tôi cần phải lấy dữ liệu theo thứ tự của danh sách liên kết. Ví dụ: được cung cấp dữ liệu này:

id | next_id 
----+--------- 
    1 |  2 
    2 |  4 
    3 |  9 
    4 |  3 
    9 | NULL 

Tôi cần tìm nạp các hàng cho id = 1, 2, 4, 3, 9 theo thứ tự đó. Làm thế nào tôi có thể làm điều này với một truy vấn cơ sở dữ liệu? (Tôi có thể làm điều đó trên đầu khách hàng. Tôi tò mò nếu điều này có thể được thực hiện ở phía cơ sở dữ liệu. Vì vậy, nói rằng nó không thể là okay (được đưa ra bằng chứng đủ)). Bạn cũng có thể có điểm kết thúc (ví dụ: dừng sau 10 lần tìm nạp hoặc khi một số điều kiện trên hàng đó chuyển thành true) nhưng đây không phải là yêu cầu (có thể được thực hiện ở phía máy khách). Tôi (hy vọng tôi) không cần phải kiểm tra các tài liệu tham khảo vòng tròn.

+0

Bạn có thể tạo thêm các bảng chỉ mục không? Tôi thực sự tò mò về kế hoạch giải thích cho truy vấn mà Bill đề xuất. Nó có thể không phải là xấu vì nó luôn luôn tìm kiếm trên khóa chính. Tôi giả định rằng bạn sẽ cung cấp ID của nút đầu tiên trong truy vấn của bạn. (nếu không, nó sẽ tàn bạo). 10 chuyến đi vòng sẽ làm điều đó (tôi biết, không phải những gì bạn yêu cầu). Bảng tạm thời được tạo trong truy vấn có thể làm điều đó, đặc biệt nếu kết quả của bạn được đặt nhỏ. – TheJacobTaylor

Trả lời

5

Một số nhãn hiệu cơ sở dữ liệu (ví dụ: Oracle, Microsoft SQL Server) hỗ trợ cú pháp SQL bổ sung để chạy "truy vấn đệ quy" nhưng MySQL không hỗ trợ bất kỳ giải pháp nào như vậy.

Sự cố bạn mô tả giống như biểu thị cấu trúc cây trong cơ sở dữ liệu SQL. Bạn chỉ có một cây dài, gầy.

Có một số giải pháp để lưu trữ và tìm nạp loại cấu trúc dữ liệu này từ RDBMS. Xem một số câu hỏi sau:


Kể từ khi bạn đề cập rằng bạn muốn để hạn chế "chiều sâu" được trả về bởi các truy vấn, bạn có thể đạt được điều này trong khi truy vấn danh sách theo cách này:

SELECT * FROM mytable t1 
LEFT JOIN mytable t2 ON (t1.next_id = t2.id) 
LEFT JOIN mytable t3 ON (t2.next_id = t3.id) 
LEFT JOIN mytable t4 ON (t3.next_id = t4.id) 
LEFT JOIN mytable t5 ON (t4.next_id = t5.id) 
LEFT JOIN mytable t6 ON (t5.next_id = t6.id) 
LEFT JOIN mytable t7 ON (t6.next_id = t7.id) 
LEFT JOIN mytable t8 ON (t7.next_id = t8.id) 
LEFT JOIN mytable t9 ON (t8.next_id = t9.id) 
LEFT JOIN mytable t10 ON (t9.next_id = t10.id); 

Nó sẽ làm hỏng m như mật đường, và kết quả sẽ trở lại tất cả trên một hàng (mỗi danh sách liên kết), nhưng bạn sẽ nhận được kết quả.

+0

Liên kết đầu tiên trông rất thú vị. Đáng buồn thay, tôi không thể thay đổi cấu trúc cơ sở dữ liệu. Nó có thể được sửa đổi bằng cách nào đó để phù hợp với nhu cầu của tôi không? Nếu không, tôi sẽ đợi xem có ai khác trả lời là 'có' không. – strager

+0

ĐÓNG CHỌN ở đó. =] Tôi sẽ chỉ nói điều này là không thể thực hiện hợp lý. Cảm ơn thông tin của bạn! – strager

+0

Vâng, tôi sẽ không đề xuất một CHỌN như thế. Nhưng bạn nói rằng bạn không thể thay đổi cấu trúc cơ sở dữ liệu - đôi khi không có lựa chọn nào khác. –

2

Đây không phải là giải pháp và nhiều giải pháp khác, nhưng đối với danh sách tuyến tính (chứ không phải là cây Bill Karwin đã đề cập), có thể hiệu quả hơn khi sử dụng cột sắp xếp trong danh sách của bạn. Ví dụ:

TABLE `schema`.`my_table` (
    `id` INT NOT NULL PRIMARY KEY, 
    `order` INT, 
    data .., 
    INDEX `ix_order` (`sort_order` ASC) 
); 

Sau đó:

SELECT * FROM `schema`.`my_table` ORDER BY `order`; 

này có những bất lợi của chèn chậm hơn (bạn phải đặt lại vị trí tất cả các yếu tố được sắp xếp quá khứ điểm chèn) nhưng phải được nhanh chóng để thu hồi vì cột theo thứ tự là lập chỉ mục.

+0

Đáng buồn thay, tôi không thể thay đổi cấu trúc cơ sở dữ liệu vì các chương trình khác phụ thuộc vào cấu trúc. Cảm ơn cho đầu vào của bạn, mặc dù! – strager

+0

Trớ trêu thay, đây là giải pháp mà người dùng bắt đầu với [câu hỏi này] (http://stackoverflow.com/questions/10594408/insert-record-into-table-with-position-without-updating-all-the -records-position), người trả lời cho biết nên được thay đổi thành kiểu danh sách liên kết mà OP đang sử dụng trong câu hỏi này! Dường như việc lưu trữ thứ tự bản ghi tùy ý trong cơ sở dữ liệu chỉ là một vấn đề khó khăn ... – octern

3

Nếu những gì bạn đang cố tránh là có nhiều truy vấn (một cho mỗi nút) và bạn có thể thêm cột, thì bạn có thể có một cột mới liên kết đến nút gốc. Bằng cách đó bạn có thể lấy tất cả dữ liệu cùng một lúc bằng id gốc, nhưng bạn vẫn sẽ phải sắp xếp danh sách (hoặc cây) ở phía máy khách.

Vì vậy, trong đây là ví dụ bạn sẽ phải:

id | next_id | root_id 
----+---------+--------- 
    1 |  2 |  1 
    2 |  4 |  1 
    3 |  9 |  1 
    4 |  3 |  1 
    9 | NULL |  1 

Tất nhiên những bất lợi của việc này như trái ngược với danh sách liên kết truyền thống hay cây là gốc rễ không thể thay đổi mà không cần viết vào một thứ tự của tầm quan trọng của O (n) trong đó n là số nút. Điều này là do bạn sẽ phải cập nhật id gốc cho mỗi nút. May mắn thay mặc dù bạn luôn luôn có thể làm điều này trong một truy vấn cập nhật duy nhất trừ khi bạn đang chia một danh sách/cây ở giữa.

+0

Giải pháp này khá tuyệt. – appl3r

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