postgreSQL-查找公共行



我有一张桌子钱包:

[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;

请参阅演示

不是最直观的解决方案,但以下对您有效吗?

由于您只需要钱包中的行,我们可以使用半联接,首先根据源IdWallets中排除不需要的行,然后与源IdWallets联接时存在的公司颜色关联

如果我们知道您的特定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
)
);

最新更新