2012-10-21 12 views
6

Umarım başlık yeterince açıktır. Basit düğümler ve ana-çocuk ilişkilendirme tablosu kullanarak veritabanında tutulan ağaç yapıları için mantıksal AND/OR uygulamıyorum.Mantıksal OR için tam dış birleştirme alternatifleri ağaç yapısı sorgusunda

nodes and their children

örnek bir ağaç yapısı sorgu aşağıdaki gibidir:: Sorgu desende

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

çift hatları A çocuğu olduğu anlamına Örnek bir ağaç Böyle bir yapıya sahip B tipi (çocuk düğümlerinin aşağısında bir yerde) VEYA C. A -> HASCHILD -> C -> HASCHILD -> E'yi içsel bir katılımla gerçekleştirdim ve A -> HASCHILD -> B -> HASCHILD -> E uygulandı bunun gibi. Hile bu iki dalı A'ya birleştirir. Bu bir OR işlem olduğundan, B dalı veya C dalı mevcut olmayabilir. Anahtar olarak A node_id ile iki dalın tüm dış birleşimlerini kullanıp kullanamayacağımı düşünebildiğim tek yöntem. ayrıntıları önlemek için, benim SQL sorgusu bu basitleştirilmiş pasajı verelim: B veya C, hiçbir şey sonları yoksa

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 

Bu sorgu aslında NODE_ID kullanarak aynı temsilen iki Farklı bağlar ve. Sonuç kümesinin tabiki yineleniyor, ancak bununla yaşayabiliyorum. Ancak bu bağlamda OR'i uygulamak için başka bir yol düşünemiyorum. AND'lar kolaydır, iç birleşimlerdir, ancak sol dış birleştirme, As'i bağlamamı sağlayan tek yaklaşımdır. Her iki dal için kukla sütunlarla UNION ALL, bir seçenek değildir çünkü bu durumda olduğu gibi bağlanamıyorum.

Burada yaptığım şeylere alternatif var mı?

GÜNCELLEME

TokenMacGuy önerisi bana şu anda var olandan daha temiz bir rota verir. UNION'u hatırlamalıydım. Önerdiği ilk yaklaşımı kullanarak, mantıksal işleçler ile sorguları ayırmak için tutarlı bir yol olacak bir sorgu deseni ayrıştırma uygulayabilirim.

Tree query decomposition

Bu bana güzel bir sonuç oluşturarak dahil güzel şey, bir sürü yapmak yardımcı olur: şu ihtimale başkasının işlemini görselleştirmek yardımcı olur, ben yapacağım ne görsel bir temsilidir Sorgu kalıbı bileşenlerinin sonuçlara bağlandığı yeri ayarlayın. Tablo veya diğer bağlam ayrıntılarını kasıtlı olarak kullanmaktan kaçındım çünkü sorduğum soru, sorguların sonuçlarına nasıl katılacağıdır. DB'deki hiyerarşiyi nasıl ele alıyorum, kaçınmak istediğim farklı bir konudur. Yorumlara daha fazla ayrıntı ekleyeceğim. Bu temel olarak bir hiyerarşi tablosuyla birlikte bir EAV tablosudur. Her ihtimale karşı burada birisi, onu görmek istiyorum ben herhangi basitleştirmelerle olmadan koşuyorum sorgu TokenMacGuy önerisini izledikten sonra geçerli:

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

bazı örnek verileri şunlardır Could: Ya Daha tamamıyla a JOIN (b UNION c) JOIN e

gibi bir öğe a JOIN c JOIN e ile a JOIN b JOIN e birleştirmek ya da sadece sonuçlanan kombine ilişkisi b ve c birliğini kullanıp katılmak için union kullanabilirsiniz ve sonuçların bazı örnekleri gerekli? – MatBailie

+0

neden teta 'children @> array [node_id]' a katılır; equijoin 'child = node_id' daha doğal olmaz mıydı? Bu tablolar arasındaki yabancı anahtar kısıtını nasıl ifade ettiniz? – SingleNegationElimination

+0

1) Lütfen tablo tanımlarını gösteriniz 2) neden çocuklarını saklıyorsunuz; normalde B ve C'nin ebeveyni depolamak için yeterli olur. 3) düğüm tipi kısıtlama, sınıf düzeninde değil, örnek düzeyinde değil (örnek seviyesinde zorlanacaktır!) – wildplasser

cevap

3

∨ için ilişkisel eşdeğer ⋃ olduğunu.

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; 
İlgili konular