Сравните каждую строку в таблице с любой другой строкой, один и только один раз

#sql #postgresql

#sql #postgresql

Вопрос:

У меня есть таблица postgres, полная записей, которые я хотел бы сравнить с любой другой записью в той же таблице. Рассмотрим эту таблицу.

 create table temp (rec char(1));
  

Заполняется этими данными:

 insert into temp (rec) values ('a');
insert into temp (rec) values ('b');
insert into temp (rec) values ('c');
insert into temp (rec) values ('d');
  

И запрашивается с помощью этого SQL:

 select a.rec, b.rec
from temp a, temp b 
  

Это возвращает 16 строк (как и ожидалось), но включает дополнительные строки, где ‘a’ = ‘a’ и ‘b’ = ‘b’. Чтобы удалить их, я могу изменить запрос на.

 select a.rec, b.rec
from temp a, temp b 
where a.rec <> b.rec
  

Это сокращает результаты до 12 строк:

 "a" - "b"
"a" - "c"
"a" - "d"
"b" - "a"
"b" - "c"
"b" - "d"
"c" - "a"
"c" - "b"
"c" - "d"
"d" - "a"
"d" - "b"
"d" - "c"
  

Тем не менее, он по-прежнему возвращает некоторые дубликаты, он не только возвращает запись, где ‘a’ = ‘b’, но также возвращает ‘b’ = ‘a’, что меня не интересует (я уже сравнил запись ‘a’ с записью ‘b’, поэтому не заинтересован в том, чтобы делать то же сравнение наоборот)

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

Ответ №1:

Используйте distinct с вашим последним запросом:

 select distinct least(a.rec, b.rec), greatest(a.rec, b.rec)
from temp a
  cross join temp b 
where a.rec <> b.rec;
  

Выражение least(a.rec, b.rec), greatest(a.rec, b.rec) превращается b,a в a,b и distinct затем удаляет дубликаты.

Онлайн-пример:https://rextester.com/TDZQ5153

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

1. Спасибо horse_with_no_name — это действительно полезно для меня. Мой текущий запрос фактически содержит 10 из тысяч строк данных, что приводит к 100 миллионам результатов. Ваше решение значительно сокращает это и значительно сокращает время обработки.

Ответ №2:

Просто измените свое условие на < :

 select a.rec, b.rec
from temp a join
     temp b 
     on a.rec < b.rec;