Сравнение 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];