SQL中的菱形结构

问题描述

问题

给出以下表结构,其中BC提供辅助信息并用作AD间的关联表。

A <- B
^    |
|    v
C -> D 

对于a中的给定记录A,是否有可能检索B C中的数据并将其映射到D中与a相关的给定值或一组值?

示例方案

作为一个示例,假设a中的记录A代表一家公司,并且D包含它可能购买或出售的产品,并且B和{ {1}}代表其购买和销售价格。因此,对于给定的公司C,要求购买价格和销售价格的清单是很合理的,这需要aBC的组合。>

我的第一个想法是将DB都连接到一个复合表中。然后使用复合表将C中的记录映射到A中的记录。如下所示就足够了:

D

尽管我不确定这是解决此问题的最佳方法

在戈登·利诺夫(Gordon Linoff)的建议下,我提供了以下数据作为示例:

# sql Alchemy
prices = B.join(C,B.a_id==C.a_id and B.d_id==C.d_id)
A.join(prices,A.id==prices.a_id).join(D,D.id == prices.D_id)

# sql (like)
SELECT B.A_ID OR C.A_ID as A_ID,B.PRICE AS B,C.PRICE AS C,B.D_ID OR C.D_ID 
as D_ID,FROM B,C
WHERE B.D_ID = C.D_ID AND B.A_ID = C.A_ID

预期结果如下

         A                               B             
  -----------------             ----------------------  
   ID |   Name                   A_ID | D_ID | Price   
  -----------------             ----------------------  
    1 | A Company                   1 |    1 |    10   
  -----------------                 1 |    3 |    30   
                                ----------------------

         C                                D                               
----------------------             -----------------                                  
 A_ID | D_ID | Price                 ID |   Name                                     
----------------------             -----------------                                  
    1 |    2 |   -20                  1 | Apples                                     
    1 |    3 |   -30                  2 | Bananas
----------------------                3 | Cucumbers
                                   -----------------

最小工作(损坏)示例

在Phillipxy的建议下,这是最小工作 example (Click here @Phillipxy)

注释

  • 我在上面使用了sql Alchemy表示法,但我也对纯sql答案感到满意。

  • 我已经看过相关的问题,并且将 Result (A.ID=1) ------------------------------------- A | B | C | D ------------------------------------- A Company | 10 | - | Apples A Company | - | -20 | Bananas A Company | 30 | -30 | Cucumbers ------------------------------------- D表都加入C似乎很常见,但是我没有发现任何然后加入该组合的人返回到D的表,例如A。更进一步,我还没有看到将A -> (B + D + C)B压缩在一起的答案,因此人们可以将C加入A,例如D。如果有一种更好的方法可以按照要求的方式合并所有四个表,则我愿意提出建议。

  • 单击 example 按钮将带您进入S.E.一个模拟示例的查询环境(不幸的是,禁止在临时表上设置外键)

解决方法

假设B和C在(a_id,d_id)上都是唯一的:

SELECT B.PRICE AS B,C.PRICE AS C,D.NAME AS D
FROM D
LEFT JOIN B ON B.D_ID = D.ID
LEFT JOIN C ON C.D_ID = D.ID
WHERE B.PRICE IS NOT NULL OR C.PRICE IS NOT NULL
,

我发现我可以将两个表BC缝合在一起,如下所示:

SELECT 
   (case when B.A_ID is not null
         then
             B.A_ID
         else
             C.A_ID
         end) A_ID,B.Price,C.Price,(case when B.D_ID is not null
         then
             B.D_ID
         else
             C.D_ID
         end) D_ID
FROM B FULL OUTER JOIN C ON B.A_ID = C.A_ID AND B.D_ID = C.D_ID;

将以上内容与表AD结合起来可以得到以下查询:

SELECT A.Name,M.Sales,M.Purchase,D.Name
FROM A
JOIN (
SELECT 
   (case when B.A_ID is not null
        then
            B.A_ID
        else
            C.A_ID
            end) A_ID,B.Price as Sales,C.Price as Purchase,(case when B.D_ID is not null
        then
            B.D_ID
        else
            C.D_ID
            end) D_ID
   FROM B FULL OUTER JOIN C ON B.A_ID = C.A_ID AND B.D_ID = C.D_ID) M ON A.ID = M.A_ID
JOIN D ON D.ID = M.D_ID  

读起来有点像弗兰肯斯坦的怪物的挚爱孩子,以及从未入学的《大白鲨》演员成员都编码为ASCII;因此,在分配“刻度”之前,我将等待更好的建议。

,

我认为您的解决方案很好,就我个人而言,我希望COALESCE将其缩短一点

SELECT A.Name,D.Name
FROM A JOIN (
   SELECT 
   COALESCE(B.A_ID,C.A_ID) AS A_ID,COALESCE(B.D_ID,C.D_ID) AS D_ID
   FROM B FULL OUTER JOIN C ON B.A_ID = C.A_ID 
                           AND B.D_ID = C.D_ID) M ON A.ID = M.A_ID
JOIN D ON D.ID = M.D_ID  

John M. Owen的方法也是可能的,只需添加第二张桌子

SELECT A.NAME AS A,B.PRICE AS B,D.NAME AS D 
FROM A
CROSS JOIN D
LEFT JOIN B ON B.D_ID = D.ID AND B.A_ID = A.ID
LEFT JOIN C ON C.D_ID = D.ID AND C.A_ID = A.ID
WHERE B.PRICE IS NOT NULL OR C.PRICE IS NOT NULL