1
votes

Puis-je utiliser la méthode IN dans l'instruction LIKE?

J'ai un tableau qui stocke un ensemble de questions. Chaque question liée à un minimum de 1 et au maximum de 3 sujets.

SELECT * FROM questions
WHERE subject1 LIKE '1,%'  OR subject2 LIKE '1,%'  OR subject3 LIKE '1,%'
 OR   subject1 LIKE '17,%' OR subject2 LIKE '17,%' OR subject3 LIKE '17,%'
 OR   subject1 LIKE '5,%'  OR subject2 LIKE '5,%'  OR subject3 LIKE '5,%'

Un sujet est stocké comme une combinaison de sujet, section et chapitre avec une virgule , séparés. Voici quelques exemples de mes données.

| id |  question   | subject1 | subject2 | subject3 |     created_at     | 
--------------------------------------------------------------------------
| 1  | some text.. |  1,      | 17,      |  9,33,5  | 2019-01-12 11:45:26
| 2  | some text.. | 17,22,98 |  1,      | 12,10    | 2019-02-22 15:23:10
| 3  | some text.. |  9,33    |          |          | 2019-03-13 12:04:43
| 4  | some text.. | 17,      |  5,      |  1,      | 2019-04-05 05:30:12

J'ai besoin d'obtenir la question avec des sujets liés à [1,17,5] où ils sont données dynamiques. Pour cela, j'utilise la requête ci-dessous.

QUESTION_TABLE
---------------
id          => INT (primary key)
question    => VARCHAR
subject1    => VARCHAR
subject2    => VARCHAR
subject3    => VARCHAR
created_at  => DATETIME

Il y aura 3 senario de recherche.
* sujet, section et chapitre LIKE '17, 22,98
* subejct et section LIKE '17, 22,% '
* subejct uniquement LIKE '17,% '

Existe-t-il un autre moyen de réduire cette complexité dans la requête? Puis-je utiliser la méthode IN dans l'instruction LIKE ?

Remarque : je ne peux pas changer le mode de structure. Le projet est déjà implémenté par un autre utilisateur et je n'ai pas beaucoup de temps pour changer la structure. Alors s'il vous plaît, comprenez la situation.


6 commentaires

peut-être êtes-vous à la recherche de find_in_set


Si dans subject1 il n'y a qu'une seule valeur, y a-t-il une virgule à la fin ou est-ce une faute de frappe?


Il n'y a donc pas de «1» ou «17», mais «1» et «17».


@forpas: Non, ce n'est pas une faute de frappe. Chaque valeur représente, la première valeur est sujet et la seconde est section et la dernière est chapitre . S'il n'y a qu'un sujet , il devient 17, . À l'aide de la virgule , et de la position, nous détectons le sujet, la section et le chapitre id


Existe-t-il un autre moyen de réduire cette complexité dans la requête? Oui, il y a: Normaliser votre modèle de données.


@dnoeth: Ça ne peut pas. Comme je l'ai mentionné, il est implémenté par un autre utilisateur et il existe de nombreuses conditions qui utilisent cette structure. Il n'est donc pas facile de changer la structure.


3 Réponses :


0
votes

Vous pouvez essayer d'utiliser find_in_set()

SELECT * FROM questions WHERE find_in_set(subject1,(1,17,5))>0 
OR find_in_set(subject2,(1,17,5))>0 OR find_in_set(subject3,(1,17,5))>0


1 commentaires

Pardon. Cela ne fonctionne pas car je dois rechercher avec la chaîne commençant par 1, ou 17, ou 5,



2
votes

Vous pouvez utiliser RegExp avec la condition OR

SELECT * FROM QUESTION_TABLE
WHERE subject1 REGEXP  "^(1|17|5),+"
OR subject2 REGEXP  "^(1|17|5),+"
OR subject3 REGEXP  "^(1|17|5),+";

DEMO

Vous pouvez changer RegExp selon vos besoins

par exemple pour le sujet 17 et la section 22 puis REGEXP ('^ 17,22, +')


8 commentaires

Celles-ci semblent être des valeurs à deux chiffres avec un espace au début, passez à WHERE subject1 REGEXP '(1 | 17 | 5), +' à la place


Ya. J'ai aussi essayé avec REGEXP . Mais cela peut provoquer une erreur lorsque 22,11,555 .


J'ai aussi essayé avec ce subject1 REGEXP ('^ ([1] [7] | [1] | [5]),') et j'ai obtenu le résultat exact. Avez-vous une meilleure solution?


@Nishal Je pense qu'il ne détecte pas 7, vérifiez ici db- fiddle.com/f/38edTCm33XHkjQpiNC9woy/4


cela ne résultera pas lorsque je recherche 9,33,5 . Pour cela, je pense que nous devons rechercher comme subject1 REGEXP ('^ (17, | 1, | 9,33,5) +')


ici 9 33 5 tous sont soumis? ou sujet, section, chapitre


9 - Objet, 33 - Section. 5 - Chapitre. si le sujet, la section et le chapitre existent alors 9,33,5 . Il n'y aura pas de virgule , à la fin. C'est pourquoi j'ai ajouté dans mon résultat comme subject1 REGEXP ('^ (17, | 1, | 9,33,5) +')


oui, c'est pourquoi j'ai ajouté par exemple dans ma réponse, selon vos besoins, vous pouvez changer l'expression régulière. Je ne donne la réponse que pour le sujet 1 | 17 | 5 votre réponse ci-dessus est correcte s'il y a 17 | 1 | 9,33,5



0
votes

Je trouve une solution en utilisant REGEXP

SELECT * FROM questions
WHERE subject1 REGEXP  ('^(17,|1,|5,)+')
 OR   subject2 REGEXP  ('^(17,|1,|5,)+')
 OR   subject3 REGEXP  ('^(17,|1,|5,)+')

Quelqu'un a-t-il une meilleure solution? ce n'est pas facile de générer cette requête s'il existe un scénario avec une recherche de 17,255,303 ou 1405,555,


1 commentaires

Remplacez + au moins un caractère par * zéro ou plusieurs caractères REGEXP '^ (17,255,303 | 1405 , 555, | 5,) * '