如果任何字段匹配,如何将postgres表的结果分组?

时间:2018-06-23 23:39:30

标签: sql postgresql

我有一个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

有什么办法吗?

1 个答案:

答案 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发生更改,我们正在读取新“组”的第一行。

db<>fiddle