2010-02-23 40 views
6

Tôi đang làm việc với một cấu trúc cây trong MySQL được respresented bằng cách sử dụng mô hình bộ lồng nhau.Làm thế nào để CHỌN trẻ em và tổ tiên ngay lập tức tất cả trong cùng một truy vấn

Tôi hy vọng một số chuyên gia sql có thể giúp tôi xây dựng truy vấn SELECT.

Tôi muốn có thể kết hợp một tập hợp các nút bằng cách sử dụng LIKE. Đối với mỗi nút được khớp, tôi cũng cần một danh sách được phân tách bằng dấu phẩy của tổ tiên của nút đó và một danh sách được đánh dấu bằng dấu phẩy của các nút con ngay lập tức của nút đó.

Tôi không thực sự chắc chắn nên bắt đầu từ đâu - nếu một điều như vậy thậm chí có thể thực hiện được trong một truy vấn. (Hiện tại tôi đang hoàn thành điều này với một truy vấn bên trong một vòng lặp.) Những gì tôi hy vọng là một tập hợp kết quả trông giống như thế này ....

Bắt đầu bằng chuỗi "qu" và truy vấn Bảng " Nội dung "Tôi nhận được ...

Node  | Parent Nodes    | Immediate Children 
Quads  Leg, Lower Body, Muslces  Vastus Lateralus, Vastus Medialis, Rectus Femoris 
Obliques Core, Trunk, Muscles   Inner obliques, outer obliques 

Bất kỳ đề xuất nào về cách thực hiện điều này mà không có truy vấn lặp sẽ được đánh giá cao.

+0

Tôi hiện không có thời gian để viết một câu trả lời hoàn chỉnh, nhưng nếu bạn có quyền truy cập vào sách SQL Cookbook, chương về truy vấn heirarchical bao gồm sử dụng MySQL để giải quyết vấn đề này. Đối với MySQL, bạn cần phải biết chi tiết về chiều sâu để sử dụng các truy vấn, nhưng đó không phải là vấn đề - bạn biết bạn muốn đi sâu bao nhiêu. Giải pháp không phải là siêu tầm thường, nhưng có thể. –

+0

@shsimsimulator - cảm ơn, tôi sẽ xem liệu tôi có thể theo dõi cuốn sách đó không. – Travis

+0

máy fax, tôi không đồng ý. nó là tầm thường để giải quyết nếu bạn biết chiều sâu bạn cần - chén thánh đang làm nó cho chiều sâu tùy ý. Hoặc cũng không phải chén thánh, nhưng ya'know, chiều sâu tùy ý là những gì làm cho vấn đề này thú vị IMO –

Trả lời

0

khi tôi đồng ý với nickf rằng đây là xấu và dơ bẩn, nó vẫn vui vẻ, vì vậy ở đây đi:

SELECT  base.left_id, base.ancestors, 
      GROUP_CONCAT(children.left_id) children 
FROM  (
      SELECT  base.left_id 
      ,   GROUP_CONCAT(ancestors.left_id) ancestors 
      FROM  nested_set base 
      LEFT JOIN nested_set ancestors 
      ON   base.left_id  BETWEEN ancestors.left_id 
              AND ancestors.right_id 
      WHERE  base.name LIKE '%criteria%' 
      GROUP BY base.left_id 
      ) base          
LEFT JOIN nested_set children 
ON   children.left_id BETWEEN base.left_id 
           AND base.right_id 
LEFT JOIN nested_set inbetween 
ON   inbetween.left_id BETWEEN base.left_id 
           AND base.right_id 
AND  children.left_id BETWEEN inbetween.left_id 
           AND inbetween.right_id  
WHERE  inbetween.left_id IS NULL 
GROUP BY base.left_id 

Về cơ bản, Bí quyết là để giải quyết nó theo hai bước: đầu tiên, giải quyết vấn đề tổ tiên, và bí mật tổ tiên thành một danh sách với, sau đó, sử dụng kết quả này để giải quyết nó cho trẻ em.

Phần tổ tiên tương đối dễ, đó là truy vấn con trong mệnh đề từ trong giải pháp của tôi. Trẻ em khó hơn một chút. Nó hoạt động bằng cách lấy tất cả các con cháu, và sau đó yêu cầu rằng không tồn tại bất kỳ nút nào giữa nút cơ sở và con cháu, mà về cơ bản hạn chế con cháu chỉ với con cái.

Có các biến thể khác cho chiến lược này để giải quyết vấn đề này - ví dụ bạn có thể làm con đầu tiên và giải quyết tổ tiên bằng truy vấn con trong danh sách SELECT.

+0

Cảm ơn bạn đã trả lời của bạn. Tôi sẽ dành thời gian làm việc với đoạn mã của bạn ở trên để xem liệu tôi có thể làm cho nó hoạt động cho tôi hay không. Là một sang một bên, bạn cũng cho rằng điều này sẽ là một điều xấu để thực sự thực hiện. Nó thực sự là một ý tưởng tồi? Tôi phải giả định một giải pháp như thế này sẽ được * đáng kể * nhanh hơn so với các truy vấn vòng lặp nhỏ hơn. Cảm ơn một lần nữa. – Travis

+0

Vâng, vấn đề là, bộ lồng nhau là một rắc rối thực sự để có được quyền. Đầu tiên lên phía trước để duy trì dữ liệu trong cấu trúc này, sau đó truy vấn nó. Những gì tôi đặc biệt không thích là một cách thay đổi nhỏ xuống bên trái trong cây về cơ bản viết lại toàn bộ cây trên cùng và bên phải của thay đổi địa phương đó: một cơn ác mộng khả năng mở rộng. Sau đó, tôi nhìn vào những cây tiêu biểu mà tôi xử lý: chúng thường khá nhỏ, chủ yếu là đọc và tương đối tĩnh. Tôi thường kết thúc với một danh sách kề + mã ứng dụng, hoặc một con đường vật hoá, hoặc một bảng đóng cửa tùy thuộc vào những gì tôi cần vào lúc này. –

+0

Tôi đã phải thay đổi một vài điều nhỏ để làm cho nó hoạt động với thiết lập của tôi, nhưng nó hoạt động như một sự quyến rũ. Vì tốc độ là một mối quan tâm lớn đối với tôi, tôi sẽ sử dụng nó. Cảm ơn một lần nữa rất nhiều. – Travis

0

Trong một truy vấn? Tôi sẽ không bận tâm. SQL sẽ là khủng khiếp, và có lẽ thậm chí không hiệu quả. Tách từng bit thành các truy vấn nhỏ hơn hợp lý: đầu tiên tìm tất cả các nút phù hợp, sau đó cho từng nút, thông tin bổ sung bạn cần.

+0

Đó là những gì tôi hiện đang làm. Tôi bắt đầu bằng cách chọn các nút khớp với LIKE. Sau đó, tôi lặp qua chúng, và truy vấn riêng cho tổ tiên và trẻ em trên mỗi lần lặp. Tùy thuộc vào kích thước của resultset ban đầu, có thể có rất nhiều truy vấn ... – Travis

+2

okay Tôi nhận được điều đó, nhưng vì vậy những gì? Tôi vẫn thích đọc/duy trì một số truy vấn nhỏ hơn, thực hiện một hàm duy nhất, được hiểu rõ hơn, chứ không phải là một hành vi khổng lồ không thể đọc được cho tất cả trừ các bậc thầy siêu. – nickf

+0

Vâng, tôi không phải là siêu guru. :) Tôi chỉ đang cố gắng tối ưu hóa SQL của mình. Tôi đã luôn luôn hiểu rằng ngay sau khi bạn bắt đầu lặp các truy vấn sql của bạn, thảm họa là ngay quanh góc. – Travis

0

Tôi không chắc chắn 100% những gì bạn muốn nhưng nếu tôi hiểu chính xác bạn có thể đạt được điều này bằng cách sử dụng lược đồ cơ sở dữ liệu chuẩn hóa và truy vấn phụ.

Ví dụ:

Bảng "nút" Bảng "node_parents"

Các "nút" bảng sẽ lưu trữ tất cả các nút, và "node_parents" sẽ lập bản đồ các mối quan hệ giữa các nút khác nhau.

Vì vậy, khi bạn chọn NHƯNG một nút nhất định, bạn có thể lấy tất cả cha mẹ và con của nó từ node_parents.

Bạn có thể lấy thông tin bổ sung bằng cách sử dụng kết nối hoặc truy vấn con.

+0

Vấn đề là bạn chỉ có thể xử lý một cấp với cách tiếp cận đó. –

+0

trên giây, suy nghĩ, vâng điều này là lộn xộn, bạn sẽ không thể làm điều đó bằng cách sử dụng chỉ cần 1 truy vấn afaik. bạn sẽ cần phải ít nhất sử dụng một thủ tục lưu trữ để vòng lặp –

0

Câu hỏi này khó hơn rất nhiều sau đó tôi dự đoán trong bài đăng khác của bạn, nhưng tôi không đồng ý với câu trả lời áp phích đầu tiên.

Tôi khá tự tin rằng có thể có một truy vấn.

Bạn cần sử dụng SUBQUERIES và lựa chọn. Bạn đã bao giờ xem bản demo thực sự tốt trên trang web mySQL về Mô hình danh sách adjacency.

Vì bạn có thể THÍCH cho "Nút", bạn có thể sử dụng các truy vấn phụ cho truy vấn SQL của bạn để có được tất cả phụ huynh và cha mẹ. Một trong những truy vấn của tôi mà tôi đã làm một cái gì đó như thế này là hoàn toàn lớn! Nhưng nó hoạt động.

Hãy xem: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Đây chỉ là một đoạn mã nhỏ trong đó cho thấy cách những đứa trẻ ngay lập tức được tìm thấy.

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