2017-01-19 7 views
0

У меня есть 2 таблицы:PostgreSQL - Как удалить дубликаты при выполнении LEFT OUTER JOIN с предложением WHERE?

users table 
+--------+---------+ 
| id  | integer | 
+--------+---------+ 
| phone | string | 
+--------+---------+ 
| active | boolean | 
+--------+---------+ 

statuses table 
+---------+---------+ 
| id  | integer | 
+---------+---------+ 
| user_id | integer | 
+---------+---------+ 
| step_1 | boolean | 
+---------+---------+ 
| step_2 | boolean | 
+---------+---------+ 

Я делаю LEFT OUTER JOINstatuses стол на users стол с WHERE пункта, как это:

SELECT users.id, statuses.step_1, statuses.step_2 
FROM users 
LEFT OUTER JOIN statuses ON users.id = statuses.user_id 
WHERE (users.active='f') 
ORDER BY users.id DESC 

Моя проблема

Есть некоторые пользователи, имеют тот же номер телефона внутри таблицы users, и я хочу удалить дубликатов пользователей по телефону номер.

Я не хочу удалять их из базы данных. Но просто хотите исключить их только для этого запроса.

Например, John (ID: 1) и Sara (ID: 2) используют один и тот же номер телефона (+ 6012-3456789), удаляя один из них, Джон или Сара прекрасно подходят для меня.

Что я пробовал, но не работал?

Первое:

SELECT DISTINCT users.phone 
FROM users 
LEFT OUTER JOIN statuses ON users.id = statuses.user_id 
WHERE (users.active='f') 
ORDER BY users.id DESC 

Второе:

SELECT users.phone, COUNT(*) 
FROM users 
LEFT OUTER JOIN statuses ON users.id = statuses.user_id  
WHERE (users.active='f') 
GROUP BY phone 
HAVING COUNT(users.phone) > 1 
+0

Что вы подразумеваете под «Я хочу удалить один из них»? вы хотите удалить связанную таблицу строк строк? – scaisEdge

+0

@scaisEdge не удалять, а просто хотят их исключить. –

+0

Добавьте пример данных таблицы и ожидаемый результат. Помните, что SELECT DISTINCT применяется ко всем выбранным строкам. – jarlh

ответ

0

Вот один из способов

автообъединение таблицы пользователей и присоединиться с помощью телефонных номеров и фильтровать один из дублированного имени по оператор сравнения.

SELECT * 
FROM (SELECT u.* 
     FROM users u 
       JOIN users u1 
       ON u. u.phone = u1.phone -- to 
        AND u.name >= u1.name) u 
     LEFT OUTER JOIN statuses 
        ON users.id = statuses.user_id 
WHERE (users.active = 'f') 

или использовать ROW_NUMBER

Сформировать номер строки для каждого номера телефонов и фильтровать первый номер телефона с номером строки в 1

SELECT * 
FROM (SELECT u.*, 
       Row_number()OVER(partition BY phone ORDER BY name) rn 
     FROM users u) u 
     LEFT OUTER JOIN statuses 
        ON users.id = statuses.user_id 
WHERE (users.active = 'f') 
     AND rn = 1 
+0

Можете ли вы объяснить, что вы здесь делаете? –

+0

@ ZulhilmiZainudin - Ничто не может объяснить здесь его простое соединение. –

1

Я хотел бы сделать это , прежде чем делать соединения. В Postgres, select distinct on очень полезная конструкция:

SELECT u.id, s.step_1, s.step_2 
FROM (SELECT distinct on (phone) u.* 
     FROM users u 
     WHERE u.active = 'f' 
     ORDER BY phone 
    ) u LEFT OUTER JOIN 
    statuses s 
    ON u.id = s.user_id 
WHERE u.active = 'f' 
ORDER BY u.id DESC; 

distinct on возвращает один ряд для все, что в скобках. В этом случае это будет phone (на основе «Я хочу удалить дубликатов пользователей на основе номера телефона»). Тогда join не должен показывать их как дубликаты.

+0

Можете ли вы объяснить, что вы здесь делаете? –