2012-06-13 15 views
14

Cách tốt nhất để lưu trữ "danh sách có thứ tự" trong cơ sở dữ liệu là gì, để cập nhật chúng (thêm, xóa và thay đổi thứ tự các mục nhập) có thể dễ dàng thực hiện?Cách tốt nhất để lưu trữ danh sách được sắp xếp trong cơ sở dữ liệu là gì?

Xem xét cơ sở dữ liệu nơi bạn có bảng cho người dùng và phim. Mỗi người dùng có một danh sách các bộ phim yêu thích.

Vì nhiều người dùng có thể thích cùng một bộ phim, tôi đã làm cho người dùng và phim phân tách các bảng và sử dụng bảng thứ ba để kết nối chúng, các tiện ích.

usermovies chứa id của người dùng và phim và "số đơn đặt hàng". Số thứ tự được sử dụng để đặt hàng danh sách phim cho người dùng.

Ví dụ, người dùng Josh có thể có danh sách sau đây:

  1. Prometheus
  2. Men in Black 3
  3. nhà độc tài

và sử dụng Jack có thể có một danh sách như:

  1. Độc tài
  2. Prometheus
  3. Battleship
  4. Snow White and the Huntsman

Vì vậy, họ chia sẻ một số yêu thích, nhưng không nhất thiết phải theo thứ tự.

Tôi có thể lấy danh sách các ID phim cho mỗi người dùng sử dụng một truy vấn:

SELECT movie_id FROM usermovies WHERE user_id =? ORDER BY order_number 

Sau đó, với sự movie_ids ra lệnh, tôi có thể nhận được danh sách các phim sử dụng một truy vấn

SELECT name FROM movies WHERE id in (?,?,?) ORDER BY FIELD (id, ?,?,?) 

Vì vậy, truy vấn hoạt động, nhưng việc cập nhật danh sách có vẻ thực sự phức tạp - có cách nào tốt hơn để lưu trữ thông tin này để dễ dàng lấy danh sách phim cho người dùng x, thêm phim, xóa chúng và thay đổi thứ tự của danh sách không?

+0

để có được tất cả các phim cho một người dùng mà bạn có thể sử dụng một truy vấn đơn như thế này: 'SELECT tên FROM phim INNER JOIN usermovie ON usermovie.movie_id = movies.id AND usermovie.user_id =? ORDER BY usermovie.order_number'. Và tôi không thấy những gì khó khăn với cách tiếp cận hiện tại? Để thêm phim vào một người dùng, bạn chỉ cần chèn một mục mới trong liên kết của bạn và để xóa nó, bạn xóa mục nhập đó. – Cyclonecode

+0

cảm ơn! Điều đó sẽ có ích, mặc dù vấn đề thực sự của tôi ở đây là việc cập nhật. – wannabeartist

Trả lời

5

Bảng nối/nối kết với các cột bổ sung cho thuộc tính của liên kết giữa phim và người dùng là cách tiêu chuẩn để thực hiện liên kết nhiều người với lớp liên kết - vì vậy những gì bạn đã làm có vẻ đúng.

Về tính dễ chèn/cập nhật/xóa, bạn sẽ phải quản lý toàn bộ liên kết (tất cả các hàng cho FK người dùng phim) mỗi khi bạn thực hiện chèn/cập nhật/xóa. Có lẽ không phải là một cách đơn giản để làm điều này.

Sau khi nói điều này, bạn cũng sẽ cần phải chạy các hoạt động này trong một giao dịch và quan trọng hơn là có cột 'phiên bản' trên bảng giao diện này nếu ứng dụng của bạn có khả năng đa người dùng.

+0

Thực tế, * có * cách "huyền diệu" để thực hiện tác vụ chỉ thay đổi một hàng thay vì tất cả các hàng: http://stackoverflow.com/a/3399334/2947812 –

3

Để lấy người sử dụng yêu thích phim ảnh mà bạn có thể sử dụng một truy vấn duy nhất:

SELECT um.order_number, m.name FROM movies m 
INNER JOIN usermovies um ON m.id = um.movie_id 
WHERE um.user_id = ? 
ORDER BY um.order_number 

Để thêm/xóa một bộ phim yêu thích chỉ cần thêm/gỡ bỏ các biểu ghi liên quan trong usermovies bảng.
Để thay đổi thứ tự phim, chỉ cần thay đổi tất cả các trường order_number trong user_movies bảng liên quan đến người dùng.

+0

Cảm ơn, Tôi vẫn không chắc chắn cách xử lý các thay đổi mặc dù: Ví dụ: xóa phim đầu tiên cũng có nghĩa là thay đổi thứ tự của tất cả các phim khác, phải không? – wannabeartist

+0

@wannabeartist: vâng, chắc chắn – Marco

+0

Sau đó sẽ có ý nghĩa khi tạo lại danh sách khi cập nhật, thay vì cập nhật các hàng riêng lẻ? Ví dụ: người dùng x lấy danh sách của mình, thực hiện thay đổi và lần truy cập "lưu" -> 1. các mục nhập trước đó bị xóa với một lần 2. mục nhập mới được chèn với một lần – wannabeartist

4

Ngoài những gì người khác đã nói, sắp xếp lại các mục ưa thích hiện có có thể được thực hiện trong một câu lệnh UPDATE duy nhất, như được giải thích here.

Câu trả lời được liên kết giải thích sắp xếp lại hai mục, nhưng có thể dễ dàng khái quát hóa với bất kỳ số lượng mục nào.

3

Nếu bạn không tìm kiếm một "di chuyển lên/di chuyển xuống" kinda giải pháp, và sau đó mặc định cho thêm ở dưới cùng của danh sách, sau đây là một vài gợi ý hơn:

Chèn các hàng mới vào một cụ thể vị trí có thể được thực hiện như thế này: (chèn ở vị trí 3)

UPDATE usermovies SET order_number = ordernumber + 1 
    WHERE ordernumber > 3 and user_id = ?; 
INSERT INTO usermovies VALUES (?, 3, ?); 

Và bạn có thể xóa trong một thời trang tương tự: (xóa vị trí 6)

DELETE usermovies WHERE order_numer = 6 and user_id=?; 
UPDATE usermovies SET order_number = ordernumber - 1 
    WHERE ordernumber > 6 and user_id = ?;