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.
3 Réponses :
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
Pardon. Cela ne fonctionne pas car je dois rechercher avec la chaîne commençant par 1, ou 17, ou 5,
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),+";
Vous pouvez changer RegExp selon vos besoins
par exemple pour le sujet 17 et la section 22 puis REGEXP ('^ 17,22, +')
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
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,
Remplacez + au moins un caractère par * zéro ou plusieurs caractères REGEXP '^ (17,255,303 | 1405 , 555, | 5,) * '
peut-être êtes-vous à la recherche de
find_in_setSi 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
sujetet la seconde estsectionet la dernière estchapitre. S'il n'y a qu'unsujet, il devient17,. À l'aide de la virgule,et de la position, nous détectons le sujet, la section et le chapitreidExiste-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.