2014-02-20 2 views
0

У меня есть две базы данных с одинаковой схемой, которые я объединил, и теперь я хочу вернуть записи, которые являются возможными совпадениями.Соедините две таблицы и возвращайте строки с общим количеством N.

То есть, вернуть три записи в обновленной базе данных, которая может выглядеть следующим образом:

id  foo  bar  baz  meow  mix 
36  123  234       567 
962  123     345  456  567 
962       345 

Я хочу, чтобы иметь возможность поиска записей, которые имеют любые значения п столбцов общих (здесь п = 2, очевидно) , В этом примере записи 1 и 2 имеют одинаковые значения «foo» и «mix», а записи 2 и 3 имеют одинаковые значения «id» и «bad».

Я знаю, что это должен быть INNER JOIN, но моя проблема в том, что я хочу, чтобы он мог возвращать любые записи, которые имеют все значения n столбцов, поэтому я не знаю, к чему их присоединиться.

SELECT * FROM table t1 INNER JOIN table t2 ON ... 

Любая помощь будет принята с благодарностью!

Добавление:

@Gordon Linoff

Хорошо, что получилось! Я обобщил его для любого стола и любого количества столбцов и исключил идентичные совпадения с:

"SELECT t1.*, t2.* FROM {0} t1 JOIN {0} t2 ON {1} WHERE ({2}) BETWEEN 2 AND {3}".format(table, ' or '.join(['t1.{0}=t2.{0}'.format(c) for c in columns]), '+'.join(['(CASE WHEN t1.{0}=t2.{0} THEN 1 ELSE 0 END)'.format(c) for c in columns]),len(columns)-1) 

Спасибо!

ОБНОВЛЕНИЕ: таблица, в которой я исправляю это, имеет записи ~ 10 тыс., И это так медленно! Есть ли более быстрый способ сделать это?

+0

Может быть хорошей идеей построить функцию с 5 аргументами и возвращением числа пар. Затем запустите эту функцию снова в каждой строке, поместив функцию в предложение WHERE. – huhu78

+0

@ huhu78 Что бы это было? –

+0

функция в псевдокоде: int f (arg1, arg2, arg3, arg4, arg5) {сравнить все, числа пар, пары возврата}; затем в запросе: SELECT id FROM tab1 WHERE f (col1, col2, col3, col4, col5)> = n; Использование функции может быть более читаемым, более многоразовым, дает возможность написать функцию с несколькими шагами – huhu78

ответ

2

Вы можете сделать это с автообъединение и order by:

select t1.*, t2.*, 
     ((case when t1.id = t2.id then 1 else 0 end) + 
     (case when t1.foo = t2.foo then 1 else 0 end) + 
     (case when t1.bar = t2.bar then 1 else 0 end) + 
     . . . 
     ) as NumMatches   
from table t1 join 
    table t2 
    on t1.id = t2.id or 
     t1.foo = t2.foo or 
     t1.bar = t2.bar or 
     . . . 
order by NumMatches desc; 

Если вы хотите ровно два или более матчей, то это зависит от базы данных. В MySQL вы можете сказать having NumMatches >= 2. В других базах данных вам нужно либо повторить оператор case в предложении where, либо использовать подзапрос.

0

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

SELECT * FROM table WHERE foo=bar or foo=baz or foo=meow or foo=mix, ... 
+0

Я не хочу соответствовать foo и bar и т. Д. Вы имеете в виду «WHERE t1.foo = t2.foo OR t1.bar = t2 .bar 'Я предполагаю. Но это было бы абсурдно, так как я должен был бы выписать каждую возможную перестановку для соответствия нескольким столбцам, то есть «WHERE (t1.foo = t2.foo AND t1.bar = t2.bar) ИЛИ (t1.foo = t2.foo И t1.baz = t2.baz) "и т. Д. –

Смежные вопросы