Сравнение SQL-таблице (самосоединение)

Я пытаюсь найти повторяющиеся строки на основе смешанных столбцов. Это пример того, что у меня есть:

CREATE TABLE Test
(
   id INT PRIMARY KEY,
   test1 varchar(124),
   test2 varchar(124)
)

INSERT INTO TEST ( id, test1, test2 ) VALUES ( 1, 'A', 'B' )
INSERT INTO TEST ( id, test1, test2 ) VALUES ( 2, 'B', 'C' )

теперь если я запускаю этот запрос:

SELECT [LEFT].[ID] 
FROM [TEST] AS [LEFT] 
   INNER JOIN [TEST] AS [RIGHT] 
   ON [LEFT].[ID] != [RIGHT].[ID] 
WHERE [LEFT].[TEST1] = [RIGHT].[TEST2]

Я ожидал бы получить оба удостоверения. (1 и 2), однако я всегда возвращаю только одну строку.

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

SELECT [LEFT].[ID] 
FROM [TEST] AS [LEFT] 
   INNER JOIN [TEST] AS [RIGHT] 
   ON [LEFT].[ID] != [RIGHT].[ID] 
WHERE [LEFT].[TEST1] = [RIGHT].[TEST2] 
OR [LEFT].[TEST2] = [RIGHT].[TEST1]

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

окончательное решение, которое я придумал для производительности и результатов, было использовать объединение:

SELECT [LEFT].[ID] 
FROM [TEST] AS [LEFT] 
   INNER JOIN [TEST] AS [RIGHT] 
   ON [LEFT].[ID] != [RIGHT].[ID] 
WHERE [LEFT].[TEST1] = [RIGHT].[TEST2] 
UNION
SELECT [LEFT].[ID] 
FROM [TEST] AS [LEFT] 
   INNER JOIN [TEST] AS [RIGHT] 
   ON [LEFT].[ID] != [RIGHT].[ID] 
WHERE [LEFT].[TEST2] = [RIGHT].[TEST1]

но в целом, я, очевидно, не понимаю, почему это не работает, что означает, что я, вероятно, делаю что-то неправильно. Кто-нибудь может указать мне правильное направление?

4 ответов


не присоединяются к неравенству; кажется, что соединение и где условия инвертированы.

SELECT t1.id
FROM Test t1
INNER JOIN Test t2
ON ((t1.test1 = t2.test2) OR (t1.test2 = t2.test1))
WHERE t1.id <> t2.id

должно работать нормально.


вы получаете только оба идентификатора, если вы выбираете их:

SELECT [LEFT].[ID], [RIGHT].[ID] 
FROM [TEST] AS [LEFT] 
   INNER JOIN [TEST] AS [RIGHT] 
   ON [LEFT].[ID] != [RIGHT].[ID] 
WHERE [LEFT].[TEST1] = [RIGHT].[TEST2]

причина только одна строка, что только одна строка (а именно строку #2) имеет ТЕСТ1, равный другому ряду, УСЛОВИЕ_2.


похоже, вы очень быстро работаете в направлении Cartiesian Присоединиться. Обычно, если вы хотите вернуть дубликаты, вам нужно запустить что-то вроде:

SELECT [LEFT].*
FROM [TEST]  AS [LEFT]
INNER JOIN [TEST] AS [RIGHT]
    ON [LEFT].[test1] = [RIGHT].[test1]
        AND [LEFT].[test2] = [RIGHT].[test2]
        AND [LEFT].[id] <> [RIGHT].[id]

Если вам нужно смешать столбцы, то смешайте необходимые условия, но сделайте что-то вроде:

SELECT [LEFT].*
FROM [TEST] AS [LEFT]
INNER JOIN [TEST] AS [RIGHT]
    ON (
        [LEFT].[test1] = [RIGHT].[test2]
            OR [LEFT].[test2] = [RIGHT].[test1]
       )
        AND [LEFT].[id] <> [RIGHT].[id]

используя это, вы сравниваете справа налево и слева направо в каждом соединении, устраняя необходимость в WHERE в целом.

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


Это можно сделать без внутренних соединений, если я не ошибаюсь. Это мой первый раз, отвечая на вопрос mysql, но я просто отвечаю, чтобы получить больше очков здесь, на StackOverflow. Запятая очень важна, чтобы mysql не жаловался.

SELECT [LEFT].[ID] FROM [TEST] AS [LEFT], [TEST] AS [RIGHT] 
WHERE [LEFT].[ID] != [RIGHT].[ID] 
AND [LEFT].[TEST1] = [RIGHT].[TEST2];