我有一个postgresql记录表,其中每个记录在该表中都有一条记录,该记录至少与三个可能的字段之一匹配。
id | name | email | phone | product
----------------------------------------------------
1 | Rob A | foo@bar.com | 123 | 102
2 | Rob B | foo@bar.com | 323 | 102
3 | Rob C | foo@bcr.com | 123 | 102
4 | Rob A | foo@bdr.com | 523 | 102
5 | Rob A | foo@bar.com | 123 | 104
6 | Cat A | liz@bar.com | 999 | 102
7 | Cat B | lid@bar.com | 999 | 102
8 | Cat A | lib@bar.com | 991 | 102
我想将与“产品”匹配的所有表以及其他三个字段(名称,电子邮件,电话)的任何分组。这样组最终看起来像
id | name | email | phone | product
----------------------------------------------------
1 | Rob A | foo@bar.com | 123 | 102
2 | Rob B | foo@bar.com | 323 | 102
3 | Rob C | foo@bcr.com | 123 | 102
4 | Rob A | foo@bdr.com | 523 | 102
5 | Rob A | foo@bar.com | 123 | 104
6 | Cat A | liz@bar.com | 999 | 102
7 | Cat B | lid@bar.com | 999 | 102
8 | Cat A | lib@bar.com | 991 | 102
有什么办法吗?
答案 0 :(得分:0)
如果我们INNER JOIN
像自己一样摆放桌子
SELECT t1.id id1,
t2.id id2
FROM elbat t1
INNER JOIN elbat t2
ON t2.product = t1.product
AND (t2.name = t1.name
OR t2.email = t1.email
OR t2.phone = t1.phone)
AND t2.id > t1.id;
我们将拥有id1
中多行的“组”的最低ID。对于每个id1
,“组”中的其他成员都在id2
中。
也就是说,我们可以连接上面查询的结果,以便对于每一行,都将“组”的最低ID连接在一起。由于自己建立“组”的行或已经具有“组”的最低ID的行将找不到伙伴行,因此我们必须LEFT JOIN
。现在,我们可以使用联接的最低ID,或者如果没有联接任何伙伴行,则可以使用行本身的ID作为使用coalesce()
的“组” ID。
SELECT coalesce(x.id1, t.id) groupid,
t.*
FROM elbat t
LEFT JOIN (SELECT t1.id id1,
t2.id id2
FROM elbat t1
INNER JOIN elbat t2
ON t2.product = t1.product
AND (t2.name = t1.name
OR t2.email = t1.email
OR t2.phone = t1.phone)
AND t2.id > t1.id) x
ON x.id2 = t.id
ORDER BY coalesce(x.id1, t.id);
正如我们也按“组” ID排序一样,我们可以在任何应用程序中顺序遍历结果,并且知道,如果“组” ID发生更改,我们正在读取新“组”的第一行。