En SQL, je dois (malheureusement) souvent utiliser des LIKE
conditions " " dues à des bases de données qui violent presque toutes les règles de normalisation. Je ne peux pas changer ça maintenant. Mais cela n'a rien à voir avec la question.
De plus, j'utilise souvent des conditions comme WHERE something in (1,1,2,3,5,8,13,21)
pour une meilleure lisibilité et flexibilité de mes instructions SQL.
Existe-t-il un moyen possible de combiner ces deux choses sans écrire de sous-sélections compliquées?
Je veux quelque chose d'aussi simple qu'au WHERE something LIKE ('bla%', '%foo%', 'batz%')
lieu de cela:
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
Je travaille avec SQl Server et Oracle ici mais je suis intéressé si cela est possible dans n'importe quel SGBDR.
like any
/like all
: stackoverflow.com/questions/40475982/sql-like-any-vs-like-all . (Pour mémoire, cela a été demandé sur le forum Oracle Community Ideas community.oracle.com/ideas/11592 )Réponses:
Il n'y a pas de combinaison de LIKE & IN dans SQL, encore moins dans TSQL (SQL Server) ou PLSQL (Oracle). Cela s'explique en partie par le fait que la recherche en texte intégral (FTS) est l'alternative recommandée.
Les implémentations Oracle et SQL Server FTS prennent en charge le mot clé CONTAINS, mais la syntaxe est toujours légèrement différente:
Oracle:
Serveur SQL:
La colonne que vous interrogez doit être indexée en texte intégral.
Référence:
la source
Si vous souhaitez rendre votre relevé facilement lisible, vous pouvez utiliser REGEXP_LIKE (disponible à partir d'Oracle version 10).
Un exemple de tableau:
La syntaxe d'origine:
Et une requête simple avec REGEXP_LIKE
MAIS ...
Je ne le recommanderais pas moi-même en raison des performances pas si bonnes. Je m'en tiendrai aux différents prédicats LIKE. Donc, les exemples étaient juste pour le plaisir.
la source
vous êtes coincé avec le
sauf si vous remplissez une table temporaire (incluez les caractères génériques avec les données) et joignez-vous comme ceci:
essayez-le (en utilisant la syntaxe SQL Server):
PRODUCTION:
la source
LIKE 'bla%'
, ce qui dans l'exemple de code de l'OP? ou peut-il seulement effectuer desLIKE '%bla%'
recherches?Avec PostgreSQL, il existe la forme
ANY
orALL
:ou
où la sous-sélection renvoie exactement une colonne de données.
la source
LIKE ANY
et sontLIKE ALL
communs à tous les dialectes SQL, c'est-à-dire faisant partie du langage principal, ou spécifiques à un dialecte?= ANY
ou<> ALL
mais il ne fonctionne qu'en SQL, pas en PLSQL par exemple.Une autre solution, devrait fonctionner sur n'importe quel SGBDR:
la source
Je suggère d'utiliser une fonction utilisateur TableValue si vous souhaitez encapsuler les techniques de jointure interne ou de table temporaire illustrées ci-dessus. Cela lui permettrait de lire un peu plus clairement.
Après avoir utilisé la fonction de partage définie sur: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx
nous pouvons écrire ce qui suit sur la base d'un tableau que j'ai créé appelé "Fish" (int id, varchar (50) Name)
Les sorties
la source
Une approche consisterait à stocker les conditions dans une table temporaire (ou variable de table dans SQL Server) et à y adhérer comme ceci:
la source
Utilisez plutôt une jointure interne:
la source
Teradata prend en charge la syntaxe LIKE ALL / ANY :
ÉDITER:
jOOQ version 3.12.0 prend en charge cette syntaxe:
Ajouter des opérateurs synthétiques [NOT] LIKE ANY et [NOT] LIKE ALL
PostgreSQL
LIKE/ILIKE ANY (ARRAY[])
:démo db <> fiddle
Snowflake prend également en charge la correspondance COMME TOUT / COMME TOUS :
Exemple:
la source
tu peux même essayer ça
Fonction
Requete
la source
J'ai une solution simple, qui fonctionne au moins en postgresql , en utilisant
like any
suivie de la liste des expressions rationnelles. Voici un exemple, qui cherche à identifier certains antibiotiques dans une liste:la source
Je me demandais aussi quelque chose comme ça. Je viens de tester en utilisant une combinaison de
SUBSTRING
etIN
c'est une solution efficace pour ce genre de problème. Essayez la requête ci-dessous:la source
Dans Oracle, vous pouvez utiliser une collection de la manière suivante:
Ici, j'ai utilisé un type de collection prédéfini
ku$_vcnt
, mais vous pouvez déclarer le vôtre comme ceci:la source
Pour Sql Server, vous pouvez recourir à Dynamic SQL.
La plupart du temps, dans de telles situations, le paramètre de la clause IN est basé sur certaines données de la base de données.
L'exemple ci-dessous est un peu "forcé", mais cela peut correspondre à divers cas réels trouvés dans les bases de données héritées.
Supposons que vous ayez des personnes de table où les noms de personne sont stockés dans un seul champ PersonName comme FirstName + '' + LastName. Vous devez sélectionner toutes les personnes dans une liste de prénoms, stockée dans le champ NameToSelect dans la table NamesToSelect , ainsi que certains critères supplémentaires (comme filtré sur le sexe, la date de naissance, etc.)
Vous pouvez le faire comme suit
la source
J'ai peut-être une solution pour cela, même si cela ne fonctionnera que dans SQL Server 2008 pour autant que je sache. J'ai découvert que vous pouvez utiliser le constructeur de lignes décrit dans https://stackoverflow.com/a/7285095/894974 pour rejoindre une table «fictive» en utilisant une clause similaire. Cela semble plus complexe que ça, regardez:
Cela se traduira par tous les utilisateurs avec une adresse e-mail comme celles fournies dans la liste. J'espère que c'est utile à n'importe qui. Le problème me dérangeait depuis un moment.
la source
À partir de 2016, SQL Server comprend une
STRING_SPLIT
fonction . J'utilise SQL Server v17.4 et j'ai obtenu que cela fonctionne pour moi:la source
Si vous utilisez MySQL, le plus proche possible est la recherche en texte intégral:
Recherche en texte intégral, documentation MySQL
la source
Cela fonctionne pour les valeurs séparées par des virgules
Évalue à:
Si vous souhaitez qu'il utilise des index, vous devez omettre le premier
'%'
caractère.la source
Dans Oracle RBDMS, vous pouvez obtenir ce comportement à l'aide de REGEXP_LIKE fonction .
Le code suivant testera si la chaîne trois est présente dans l'expression de liste un | deux | trois | quatre | cinq (dans lequel le symbole de tuyau " | " signifie une opération logique OU).
L'expression précédente équivaut à:
Alors ça va réussir.
En revanche, le test suivant échouera.
Il existe plusieurs fonctions liées aux expressions régulières (REGEXP_ *) disponibles dans Oracle depuis la version 10g. Si vous êtes un développeur Oracle et que ce sujet vous intéresse, cela devrait être un bon début. Utiliser des expressions régulières avec Oracle Database .
la source
Peut-être pensez-vous que la combinaison comme celle-ci:
Si vous avez défini un index de texte intégral pour votre table cible, vous pouvez utiliser cette alternative:
la source
Pas de réponse comme ça:
En oracle aucun problème.
la source
Dans Teradata, vous pouvez utiliser
LIKE ANY ('%ABC%','%PQR%','%XYZ%')
. Voici un exemple qui a produit les mêmes résultats pour moila source
Je sais que c'est très tard, mais j'ai eu une situation similaire. J'avais besoin d'un opérateur "Like In" pour un ensemble de procédures stockées que j'ai, qui acceptent de nombreux paramètres et utilisent ensuite ces paramètres pour agréger les données de plusieurs systèmes RDBMS, donc aucune astuce spécifique au RDBMS ne fonctionnerait, cependant la procédure stockée et toutes les fonctions fonctionnera sur MS SQL Server, nous pouvons donc utiliser T-SQL pour la fonctionnalité de génération des instructions SQL complètes pour chaque SGBDR, mais la sortie doit être assez indépendante du SGBDR.
C'est ce que j'ai trouvé pour le moment pour transformer une chaîne délimitée (comme un paramètre entrant dans une procédure stockée) en un bloc SQL. Je l'appelle "Lichen" pour "LIKE IN". Tu piges?
Lichen.sql
La détection du délimiteur est peut-être planifiée, mais pour l'instant, elle est par défaut un point-virgule, vous pouvez donc simplement y mettre
default
. Il y a probablement des bogues dans cela. Le@leadingAnd
paramètre est juste une valeur de bit pour déterminer si vous voulez mettre un "ET" en tête devant le bloc afin qu'il s'intègre bien avec les autres ajouts de clause WHERE.Exemple d'utilisation (avec délimiteur dans argString)
Renvoie un nvarchar (512) contenant:
Il sautera également le bloc si l'entrée ne contient pas de délimiteur:
Exemple d'utilisation (sans délimiteur dans argString)
Renvoie un nvarchar (512) contenant:
Je vais continuer à travailler là-dessus, donc si j'ai oublié quelque chose (manifestement évident ou autre), n'hésitez pas à commenter ou à tendre la main.
la source
fais ça
ou
la source