Как сгруппировать результаты таблицы postgres, если какие-либо поля совпадают? - PullRequest
0 голосов
/ 24 июня 2018

У меня есть таблица записей 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 голосов
/ 24 июня 2018

Если мы 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. Для каждого id1 остальные члены «группы» находятся в id2.

То есть мы можем объединить результат из вышеприведенного запроса, чтобы для каждой строки был присоединен самый низкий идентификатор "группы". Поскольку строки, которые строят «группу» сами по себе, или строки, которые уже имеют наименьший идентификатор «группы», не найдут строку партнера, нам нужно LEFT JOIN. Теперь мы можем использовать объединенный младший идентификатор или идентификатор самой строки, если не было присоединено ни одной строки партнера, в качестве идентификатора «группы» с использованием coalesce().

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

Поскольку мы также упорядочиваем по идентификатору «группы», мы можем последовательно просматривать результат в любом приложении и знать, если идентификатор «группы» изменяется, мы читаем первую строку новой «группы».

дб <> скрипка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...