2012-10-21 59 views
6

Tôi hy vọng tiêu đề đủ rõ ràng. Tôi đã triển khai thực hiện logic AND/OR cho các cấu trúc cây được lưu giữ trong cơ sở dữ liệu, bằng cách sử dụng một nút đơn giản và một bảng liên kết cha-con. Một cây mẫu có cấu trúc như thế này:Các giải pháp thay thế cho phép nối ngoài đầy đủ cho hợp lý HOẶC trong truy vấn cấu trúc cây

nodes and their children

Một truy vấn cấu trúc cây mẫu được như sau:

A contains children of certain types, which in turn contain other nodes

Các dòng tăng gấp đôi trong mô hình truy vấn có nghĩa là A có một đứa trẻ của loại B (một nơi nào đó xuống các nút con của nó) HOẶC C. Tôi đã thực hiện A -> HASCHILD -> C -> HASCHILD -> E với một tham gia bên trong, và A -> HASCHILD -> B -> HASCHILD -> E được thực hiện như thế này. Bí quyết đang nối hai nhánh này vào A. Vì đây là thao tác OR, chi nhánh B hoặc nhánh C có thể không tồn tại. Phương pháp duy nhất tôi có thể nghĩ ra nếu sử dụng các kết nối bên ngoài đầy đủ của hai nhánh với node_id của A làm khóa. Để tránh chi tiết, hãy để tôi cung cấp cho đoạn đơn giản này từ truy vấn SQL của tôi:

WITH A as (....), 
    B as (....), 
    C as (....), 
    ...... 

SELECT * 
     from 
      A 
      INNER JOIN A_CONTAINS_B ON A.NODE_ID = A_CONTAINS_B.parent 
      INNER JOIN B ON A_CONTAINS_B.children @> ARRAY[B.NODE_ID] 
      INNER JOIN ..... 

      full OUTER JOIN -- THIS IS WHERE TWO As ARE JOINED 
      (select 
      A2.NODE_ID AS A2_NODE_ID 
      from 
      A2 
      INNER JOIN A_CONTAINS_C ON A2.NODE_ID = C_CONTAINS_C.parent 
      INNER JOIN C ON A_CONTAINS_C.children @> ARRAY[C.NODE_ID] 
      INNER JOIN ....) 
      as other_branch 
      ON other_branch.A2_NODE_ID = A.NODE_ID 

truy vấn này liên kết hai Như mà thực sự đại diện cho cùng một sử dụng node_id, và nếu B hoặc C không tồn tại, vi phạm gì cả. Tập hợp kết quả có bản sao tất nhiên, nhưng tôi có thể sống với điều đó. Tuy nhiên, tôi không thể nghĩ ra một cách khác để thực hiện HOẶC trong ngữ cảnh này. ANDs rất dễ dàng, chúng là các kết nối bên trong, nhưng việc kết nối bên ngoài trái là cách tiếp cận duy nhất cho phép tôi kết nối As. UNION ALL với các cột giả cho cả hai nhánh không phải là một tùy chọn vì tôi không thể kết nối Như trong trường hợp đó.

Bạn có lựa chọn thay thế nào cho những gì tôi đang làm ở đây không?

CẬP NHẬT

gợi ý TokenMacGuy của mang lại cho tôi một con đường sạch hơn so với những gì tôi có vào lúc này. Tôi nên nhớ UNION. Sử dụng phương pháp tiếp cận đầu tiên mà anh ta đã đề xuất, tôi có thể áp dụng phân tích mẫu truy vấn, đây sẽ là cách nhất quán để chia nhỏ truy vấn bằng toán tử logic. Sau đây là một hình ảnh của những gì tôi sẽ phải làm gì, chỉ trong trường hợp nó sẽ giúp người khác hình dung quá trình:

Tree query decomposition

Điều này giúp tôi làm được rất nhiều điều tốt đẹp, trong đó có việc tạo ra một kết quả tốt đẹp đặt nơi các thành phần mẫu truy vấn được liên kết với kết quả. Tôi đã cố tình tránh các chi tiết của bảng hoặc ngữ cảnh khác, bởi vì câu hỏi của tôi là về cách tham gia các kết quả truy vấn. Làm thế nào tôi xử lý các hệ thống phân cấp trong DB là một chủ đề khác nhau mà tôi muốn tránh. Tôi sẽ thêm nhiều chi tiết hơn vào các bình luận. Đây là cơ bản một bảng EAV đi kèm với một bảng phân cấp. Chỉ trong trường hợp ai đó muốn nhìn thấy nó, đây là truy vấn Tôi đang chạy mà không cần bất kỳ đơn giản hóa, sau khi làm theo gợi ý của TokenMacGuy:

WITH 
    COMPOSITION1 as (select comp1.* from temp_eav_table_global as comp1 
         WHERE 
         comp1.actualrmtypename = 'COMPOSITION'), 
    composition_contains_observation as (select * from parent_child_arr_based), 
    OBSERVATION as (select obs.* from temp_eav_table_global as obs 
         WHERE 
         obs.actualrmtypename = 'OBSERVATION'), 
    observation_cnt_element as (select * from parent_child_arr_based), 
    OBS_ELM as (select obs_elm.* from temp_eav_table_global as obs_elm 
         WHERE 
         obs_elm.actualrmtypename= 'ELEMENT'), 

    COMPOSITION2 as (select comp_node_tbl2.* from temp_eav_table_global as comp_node_tbl2 
          where 
          comp_node_tbl2.actualrmtypename = 'COMPOSITION'), 
    composition_contains_evaluation as (select * from parent_child_arr_based), 
    EVALUATION as (select eva_node_tbl.* from temp_eav_table_global as eva_node_tbl 
          where 
          eva_node_tbl.actualrmtypename = 'EVALUATION'), 
    eval_contains_element as (select * from parent_child_arr_based), 
    ELEMENT as (select el_node_tbl.* from temp_eav_table_global as el_node_tbl 
          where 
          el_node_tbl.actualrmtypename = 'ELEMENT') 



select 
         'branch1' as branchid, 
         COMPOSITION1.featuremappingid as comprootid, 
         OBSERVATION.featuremappingid as obs_ftid, 
         OBSERVATION.actualrmtypename as obs_tn, 
         null as ev_ftid, 
         null as ev_tn, 
         OBS_ELM.featuremappingid as obs_elm_fid, 
         OBS_ELm.actualrmtypename as obs_elm_tn, 
         null as ev_el_ftid, 
         null as ev_el_tn 

         from 
         COMPOSITION1 
         INNER JOIN composition_contains_observation ON COMPOSITION1.featuremappingid = composition_contains_observation.parent 
         INNER JOIN OBSERVATION ON composition_contains_observation.children @> ARRAY[OBSERVATION.featuremappingid] 
         INNER JOIN observation_cnt_element on observation_cnt_element.parent = OBSERVATION.featuremappingid 
         INNER JOIN OBS_ELM ON observation_cnt_element.children @> ARRAY[obs_elm.featuremappingid] 

UNION 

SELECT     
         'branch2' as branchid, 
         COMPOSITION2.featuremappingid as comprootid, 
         null as obs_ftid, 
         null as obs_tn, 
         EVALUATION.featuremappingid as ev_ftid, 
         EVALUATION.actualrmtypename as ev_tn, 
         null as obs_elm_fid, 
         null as obs_elm_tn, 
         ELEMENT.featuremappingid as ev_el_ftid, 
         ELEMENT.actualrmtypename as ev_el_tn      
        from 
         COMPOSITION2 
         INNER JOIN composition_contains_evaluation ON COMPOSITION2.featuremappingid = composition_contains_evaluation.parent 
         INNER JOIN EVALUATION ON composition_contains_evaluation.children @> ARRAY[EVALUATION.featuremappingid] 
         INNER JOIN eval_contains_element ON EVALUATION.featuremappingid = eval_contains_element.parent 
         INNER JOIN ELEMENT on eval_contains_element.children @> ARRAY[ELEMENT.featuremappingid] 
+0

Ông có thể bao gồm một số dữ liệu mẫu và một số ví dụ về kết quả cần thiết? – MatBailie

+0

tại sao theta tham gia 'children @> array [node_id]'; sẽ không phải là một 'con số = node_id' equijoin sẽ tự nhiên hơn? bạn đã thể hiện ràng buộc khoá ngoại giữa các bảng này như thế nào? – SingleNegationElimination

+0

1) Vui lòng cho chúng tôi biết (các) định nghĩa bảng 2) tại sao bạn lưu trữ trẻ em của một đứa trẻ; thông thường nó sẽ suffic để lưu trữ cha mẹ của B và C. 3) ràng buộc kiểu nút phải ở định nghĩa lớp, không phải ở cấp độ cá thể (mặc dù nó sẽ được thực thi ở cấp độ cá thể!) – wildplasser

Trả lời

3

tương đương với quan hệ để ∨ là ⋃.Bạn có thể có thể sử dụng union kết hợp a JOIN b JOIN e với a JOIN c JOIN e hoặc chỉ sử dụng sự kết hợp của b và c và tham gia vào các kết quả, mối quan hệ kết hợp, một cái gì đó giống như a JOIN (b UNION c) JOIN e

hoàn toàn khác:

SELECT * 
FROM a 
JOIN (
    SELECT 
     'B' source_relation, 
     parent, 
     b.child, 
     b_thing row_from_b, 
     NULL row_from_c 
    FROM a_contains_b JOIN b ON a_contains_b.child = b.node_id 

    UNION 
    SELECT 
     'C', 
     parent 
     c.child, 
     NULL, 
     c_thing 
    FROM a_contains_c JOIN c ON a_contains_c.child = c.node_id 
) a_c ON A.NODE_ID = a_e.parent 
JOIN e ON a_c.child = e.node_id;