Неравномерное самосоединение

#sql #oracle #self-join

#sql #Oracle #самосоединение

Вопрос:

У меня есть следующая таблица пользователя

Пользователи

 name    city
A       New York
B       Paris
C       London
D       London
E       Paris
  

Я хочу выбрать двух пользователей из одного города, используя неравнозначное самосоединение
таким образом, чтобы результат следовал

 name  name  city
B     E     Paris
C     D     London
  

Комментарии:

1. Пометьте, пожалуйста, вашу СУБД.

2. Пожалуйста, объясните ваше требование (не использовать equi self join).

Ответ №1:

«Самосоединение» точно так же, как и обычный join execpet, заключается в том, что одна и та же таблица отображается с обеих сторон предложения join. «неравномерный» означает поиск строк, которые не совпадают в некотором столбце.

Итак, в вашем случае вам нужно присоединиться по ГОРОДУ и отфильтровать различия в НАЗВАНИИ:

 select t1.name as t1_name
       , t2.name as t2_name
       , t1.city
from users t1
     join users t2
     on t2.city = t1.city
where t1.name < t2.name
  

Обратите внимание, что условие фильтра таково less than : использование not equals удвоит набор результатов. (*)

Очевидно, что это решение будет работать там, где CITY имеет две записи. Если имеется более двух записей, вы все равно получите несколько строк (по одной на комбинацию).


(*) Иногда желательно использовать != : если мы исследуем проблему с качеством данных, то возврат всех столбцов из обеих строк может помочь нам понять, что происходит.

Ответ №2:

Вы также можете использовать приведенный ниже способ с использованием cte

 WITH CITY
AS (
SELECT ROW_NUMBER() OVER(PARTITION BY A.CITY ORDER BY A.CITY) RNO,A.NAME,A.CITY FROM Table1 A
)

SELECT A.NAME,B.NAME,A.CITY FROM 
CITY A JOIN 
CITY B
ON 
A.city=B.city AND A.NAME<>B.name AND A.RNO<=B.RNO
  

Комментарии:

1. Не уверен, что это решение принесет участнику, но если вы собираетесь это сделать, было бы разумнее упорядочить предложение partition по ИМЕНИ, а не по ГОРОДУ.

2. Пользователю @ APC необходимо выбрать двух пользователей для одного и того же города, поэтому я использовал раздел с городом, поэтому для этого сценария результаты были ожидаемыми.

3. Я хочу сказать, что CTE увеличивает накладные расходы на стоимость выполнения, не оказывая существенного влияния на набор результатов. Итак, какое преимущество, по вашему мнению, предлагает этот запрос для оправдания дополнительных затрат?

4. @APC Я подумал, что повторное заполнение физической таблицы может быть не очень хорошей практикой, поэтому я взял результаты в cte и использовал их. Поправьте меня, если я ошибаюсь.

5. Я думаю, что это подпадает под категорию «преждевременной оптимизации». Кроме того, вы выполнили план объяснения своего решения? Попробуйте, вы можете быть удивлены! 😉