web-dev-qa-db-fra.com

comment utiliser un like avec une jointure en sql?

J'ai 2 tables, disons la table A et la table B et je veux effectuer une jointure, mais la condition de correspondance doit être où une colonne de A 'est comme' une colonne de B ce qui signifie que tout peut venir avant ou après la colonne dans B:

par exemple: si la colonne de A est 'foo'. Ensuite, la jointure correspondrait si la colonne en B est: 'fooblah', 'somethingfooblah', ou simplement 'foo'. Je sais comment utiliser les caractères génériques dans une instruction de type standard, mais je suis confus lorsque je fais une jointure. Est-ce que ça a du sens? Merci.

44
jim

Utilisation de INSTR :

SELECT *
  FROM TABLE a
  JOIN TABLE b ON INSTR(b.column, a.column) > 0

Utiliser LIKE:

SELECT *
  FROM TABLE a
  JOIN TABLE b ON b.column LIKE '%'+ a.column +'%'

Utilisation de LIKE, avec CONCAT:

SELECT *
  FROM TABLE a
  JOIN TABLE b ON b.column LIKE CONCAT('%', a.column ,'%')

Gardez à l'esprit que dans toutes les options, vous voudrez probablement conduire les valeurs des colonnes en majuscules AVANT de comparer pour vous assurer d'obtenir des correspondances sans souci de respect de la casse:

SELECT *
  FROM (SELECT UPPER(a.column) 'ua'
         TABLE a) a
  JOIN (SELECT UPPER(b.column) 'ub'
         TABLE b) b ON INSTR(b.ub, a.ua) > 0

Le plus efficace dépendra en fin de compte de la sortie plan EXPLAIN .

Les clauses JOIN sont identiques à l'écriture des clauses WHERE. La syntaxe JOIN est également appelée ANSI JOINs car elle est normalisée. Les JOIN non ANSI ressemblent à:

SELECT *
  FROM TABLE a,
       TABLE b
 WHERE INSTR(b.column, a.column) > 0

Je ne vais pas m'embêter avec un exemple de jointure non-ANSI LEFT JOIN. L'avantage de la syntaxe ANSI JOIN est qu'elle sépare ce qui joint les tables de ce qui se passe réellement dans la clause WHERE.

75
OMG Ponies

Dans MySQL, vous pouvez essayer:

SELECT * FROM A INNER JOIN B ON B.MYCOL LIKE CONCAT('%', A.MYCOL, '%');

Bien sûr, ce serait une requête massivement inefficace car elle ferait une analyse complète de la table.

Mise à jour: voici une preuve


create table A (MYCOL varchar(255));
create table B (MYCOL varchar(255));
insert into A (MYCOL) values ('foo'), ('bar'), ('baz');
insert into B (MYCOL) values ('fooblah'), ('somethingfooblah'), ('foo');
insert into B (MYCOL) values ('barblah'), ('somethingbarblah'), ('bar');
SELECT * FROM A INNER JOIN B ON B.MYCOL LIKE CONCAT('%', A.MYCOL, '%');
+-------+------------------+
| MYCOL | MYCOL            |
+-------+------------------+
| foo   | fooblah          |
| foo   | somethingfooblah |
| foo   | foo              |
| bar   | barblah          |
| bar   | somethingbarblah |
| bar   | bar              |
+-------+------------------+
6 rows in set (0.38 sec)
19
Asaph

Si c'est quelque chose que vous devrez faire souvent ... alors vous voudrez peut-être dénormaliser la relation entre les tables A et B.

Par exemple, lors de l'insertion dans la table B, vous pouvez écrire zéro ou plusieurs entrées dans une table de jonction mappant B vers A sur la base d'un mappage partiel. De même, les modifications apportées à l'une ou l'autre table pourraient mettre à jour cette association.

Tout dépend de la fréquence à laquelle les tables A et B sont modifiées. S'ils sont assez statiques, prendre un coup sur INSERT est moins douloureux que les coups répétés sur SELECT.

5
David Andres

L'utilisation de critères conditionnels dans une jointure est définitivement différente de la clause Where. La cardinalité entre les tables peut créer des différences entre les clauses Joins et Where.

Par exemple, l'utilisation d'une condition similaire dans une jointure externe conserve tous les enregistrements de la première table répertoriée dans la jointure. L'utilisation de la même condition dans la clause Where modifie implicitement la jointure en jointure interne. L'enregistrement doit généralement être présent dans les deux tableaux pour effectuer la comparaison conditionnelle dans la clause Where.

J'utilise généralement le style donné dans l'une des réponses précédentes.

tbl_A as ta
    LEFT OUTER JOIN tbl_B AS tb
            ON ta.[Desc] LIKE '%' + tb.[Desc] + '%'

De cette façon, je peux contrôler le type de jointure.

2
Geoffrey Fuller

Lorsque l'écriture de requêtes avec notre serveur LIKE ou INSTR (ou CHARINDEX en T-SQL) prend trop de temps, nous utilisons donc LEFT comme dans la structure suivante:

select *
from little
left join big
on left( big.key, len(little.key) ) = little.key

Je comprends que cela ne fonctionne qu'avec une variation de fin à la requête, contrairement à d'autres suggestions avec '%' + b + '%', mais c'est suffisant et beaucoup plus rapide si vous n'avez besoin que de b + '%'.

Une autre façon de l'optimiser pour la vitesse (mais pas la mémoire) est de créer une colonne dans "little" qui est "len (little.key)" en tant que "lenkey" et utilisateur à la place dans la requête ci-dessus.

0