我有一张桌子钱包:
[id] [address]
1 ABC
2 ABC
3 DEF
4 GHI
5 JKL
我有一张桌子卡片
[company] [color] [wallet_id]
Facebook blue 1
Facebook blue 2
Youtube red 3
Facebook blue 3
Orkut pink 4
Microsoft green 5
Facebook blue 5
我想获得所有具有相同卡的不同钱包地址,所以如果我通过钱包id 1,它应该返回:
[id] [address]
3 DEF // Because wallet with id 1 and 3 have same blue Facebook card
5 JKL // Because wallet with id 1 and 5 have same blue Facebook card
在这种情况下,它不应该返回ID为2的钱包,即使有相同的卡,因为它与我们查找的地址(ABC(相同。
我尝试了很多不同的解决方案,但我对如何组织SQL来做到这一点感到困惑。
我试着使用:
- 首先选择要查找的钱包
SELECT id, address FROM wallets w WHERE w.id = 1
- 选择此钱包的所有卡
SELECT company, color FROM cards c WHERE c.wallet_id = w.id
- 使用INNER JOIN合并这两个查询
SELECT id, address FROM wallets w INNER JOIN cards c ON w.id = c.id WHERE w.id = 1 GROUP BY id
现在我需要将上面的查询结果与具有相同卡的其他钱包合并
。。。以下是我无法继续的地方,我对如何做到这一点感到困惑:c
您可以加入每个表的2个副本,如下所示:
SELECT w2.*
FROM Wallets w1
INNER JOIN Cards c1 ON c1.wallet_id = w1.id
INNER JOIN Cards c2 ON c2.company = c1.company AND c2.color = c1.color
INNER JOIN Wallets w2 ON w2.id = c2.wallet_id AND w2.address <> w1.address
WHERE w1.id = 1;
请参阅演示
不是最直观的解决方案,但以下对您有效吗?
由于您只需要钱包中的行,我们可以使用半联接,首先根据源Id从Wallets
中排除不需要的行,然后与源Id的Wallets
联接时存在的公司和颜色关联
如果我们知道您的特定RDBMS,那么使用横向联接可能会有一个更优雅的解决方案,但是半联接可能会表现得很好。
select *
from wallets w
where not exists (
select * from wallets w2
where w2.address = w.address and w2.id = 1
) and exists (
select * from cards c
where c.Wallet_id = w.id and exists (
select *
from cards c2
join wallets w2 on w2.id = c2.Wallet_id
where w2.id = 1
and c.company = c2.company
and c.color = c2.color
)
);