Đệ quy tự tham gia


15

Tôi có một commentsbảng, có thể được đơn giản hóa để này:

comments
=======
id
user_id
text
parent_id

trong đó parent_idlà nullable, nhưng có thể là một chìa khóa cho bình luận chính của nó.


Bây giờ, làm thế nào tôi có thể selecttất cả con cháu của một nhận xét cụ thể?
Các ý kiến ​​có thể giảm một vài cấp ...

Câu trả lời:


16

Các truy vấn phân cấp , như các truy vấn đệ quy đã biết, không được hỗ trợ cho MySQL.

Tuy nhiên, chúng được hỗ trợ trong Oracle, Microsoft SQL Server, DB2 và PostgreSQL, cùng với những thứ khác.

Nếu bạn cần một cách giải quyết, bạn có thể tìm thấy một mẹo năng động (và do đó, có khả năng gây nguy hiểm) tại đây: /programming/8104187/mysql-hierarchical-queries

Bạn cũng có thể tìm thấy một cuộc thảo luận về cách lưu trữ dữ liệu phân cấp với các mô hình khác ngoài Danh sách điều chỉnh (tức là cột Cha mẹ ) tại đây: /programming/192220/what-is-the- most- hiệu quả- Elegant-way-to-parse-a-phẳng-bàn-thành-một-cây /

Chúc may mắn!


Tôi tự hỏi làm thế nào giải pháp đó trong liên kết thứ hai của bạn có thể nguy hiểm. Bạn có thể giải thích nó? Nếu không, chào mừng đến với trang web!
dezso

3
@dezso: Tự mình giải quyết vấn đề của truy vấn, Quassnoi " * Nó không nâng cấp an toàn * vì MySQL không xác định rõ ràng hành vi biến phiên. Tuy nhiên, đó là cách duy nhất để xử lý danh sách kề theo thời gian truy vấn kịp thời ." Nguy hiểm có thể là một từ quá mạnh ( có khả năng không ổn định ?) Nhưng tôi thích nhầm lẫn về mặt thận trọng (cộng với, tôi hiểu biết nhiều về Oracle hơn MySQL, vì vậy tôi muốn được tự tin hơn). Cảm ơn đã chào đón, nhân tiện! Tôi đã là một người ẩn giấu lâu năm đối với mạng SE và tôi quyết định đã đến lúc phải trả lại một chút.
Valmoer

2
Cú pháp VỚI [RECURSIVE] hiện được hỗ trợ từ mysql 8.0. dev.mysql.com/doc/refman/8.0/en/with.html
ClearCrescendo

6

Thiết kế bảng này là một antipotype SQL "Cây ngây thơ" như được mô tả bởi Bill Karwin (nhìn chằm chằm từ slide 48 trong bản trình bày SQL Antipotypes Strike Back của anh ấy ). Vấn đề với thiết kế này cụ thể là khó khăn trong việc lấy tất cả con cháu (hoặc cha mẹ) của một nút. Vì bạn đang sử dụng MySQL, bạn không thể sử dụng các biểu thức bảng chung (câu lệnh VỚI và nó là công cụ sửa đổi RECURSIVE) có trong các RDBMS khác.

Những gì bạn còn lại là:

  • sử dụng một triển khai thay thế của cấu trúc dữ liệu phân cấp (câu trả lời cho câu hỏi này có thể là một tài liệu tham khảo tốt về điều này)
  • xây dựng các truy vấn tự tham gia với một giới hạn độ sâu. Đối với độ sâu = 5 bạn có thể sử dụng một cái gì đó trong các dòng:

    SELECT *
    FROM comments AS c1
      JOIN comments AS c2 ON (c2.parent_id = c1.id)
      JOIN comments AS c3 ON (c3.parent_id = c2.id)
      JOIN comments AS c4 ON (c4.parent_id = c3.id)
      JOIN comments AS c5 ON (c5.parent_id = c4.id)
  • sử dụng RDBMS hỗ trợ VỚI RECURSIVE (mặc dù điều này rất có thể không phải là một tùy chọn cho hầu hết mọi người)


2
Tôi không đồng ý với Bill Karwin ở đây. Mô hình kề không phải là một mô hình chống. Với một DBMS hiện đại hỗ trợ các truy vấn đệ quy (Oracle đã hỗ trợ điều này trong hơn 20 năm), một mô hình như vậy rất hiệu quả để truy xuất cập nhật.
a_horse_with_no_name

5

MySQL không hỗ trợ các truy vấn đệ quy như truy vấn bạn cần.

Những gì tôi đã làm một lúc trước là viết Thủ tục lưu trữ cung cấp mô hình để làm như vậy.

Thay vì phát minh lại bánh xe, tôi sẽ cung cấp cho bạn các liên kết đến các bài đăng trước đây của tôi về điều này:

Nói tóm lại, các thủ tục được lưu trữ mà tôi đã thực hiện để sắp xếp trước giao diện cây bằng cách xử lý hàng đợi

  • GetParentIDByID
  • GetAncestry
  • GetFamilyTree

Cha mẹ cho tất cả trẻ em (như Thủ tục lưu trữ GetF FamilyTree)

  • BƯỚC01) Bắt đầu với parent_idmột hàng đợi
  • BƯỚC02) Dequeue tiếp theo parent_idnhư hiện tại
  • BƯỚC03) Ghi lại tất cả các idgiá trị có dòng điệnparent_id
  • STEP04) In hoặc Thu thập Nhận xét
  • BƯỚC05) Nếu hàng đợi không trống, goto STEP02
  • BƯỚC06) Bạn đã hoàn thành !!!

Con cho tất cả các bậc cha mẹ (như Thủ tục lưu trữ GetAncestry)

  • BƯỚC01) Bắt đầu với idmột hàng đợi
  • BƯỚC02) Dequeue tiếp theo idnhư hiện tại
  • BƯỚC03) Ghi lại parent_idgiá trị của hiện tạiid
  • STEP04) In hoặc Thu thập Nhận xét
  • BƯỚC05) Nếu hàng đợi không trống, goto STEP02
  • BƯỚC06) Bạn đã hoàn thành !!!

Vui lòng xem qua Thủ tục lưu trữ trong các bài đăng khác của tôi để xem việc thực hiện.

Hãy thử một lần !!!


2
SELECT  group_concat(@id :=
        (
        SELECT  id
        FROM    comments
        WHERE   parent_id = @id
        )) AS comment
FROM    (
        SELECT  @id := 1
        ) vars
STRAIGHT_JOIN
        comments
WHERE   @id IS NOT NULL

vĩ cầm

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.