问题描述
问题
给出以下表结构,其中B
和C
提供辅助信息并用作A
和D
之间的关联表。
A <- B
^ |
| v
C -> D
对于a
中的给定记录A
,是否有可能检索B
和 C
中的数据并将其映射到D
中与a
相关的给定值或一组值?
示例方案
作为一个示例,假设a
中的记录A
代表一家公司,并且D
包含它可能购买或出售的产品,并且B
和{ {1}}代表其购买和销售价格。因此,对于给定的公司C
,要求购买价格和销售价格的清单是很合理的,这需要a
,B
和C
的组合。>
我的第一个想法是将D
和B
都连接到一个复合表中。然后使用复合表将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) 。
注释
-
我已经看过相关的问题,并且将
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
。如果有一种更好的方法可以按照要求的方式合并所有四个表,则我愿意提出建议。
解决方法
假设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
,
我发现我可以将两个表B
和C
缝合在一起,如下所示:
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;
将以上内容与表A
和D
结合起来可以得到以下查询:
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