Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

requete de recherche multi-critère

4 réponses
Avatar
Pif
Bonjour, je suis en Java/MySQL.
J'ai une table qui contient des relations entre éléments, et ces
relations peuvent avoir des attributs (actuellement 4, ...)

id1, id2, attr_rel1, attr_rel2, attr_rel3, attr_rel4, ...

Je voudrais créer une méthode Java qui me liste les relations, en
spécifiant parfois le premier id, parfois le second (c'est pas pareil,
mes relations peuvent être orientées), parfois les deux, et en
choisissant parfois de retreindre suivant plusieurs critères (1 à 4)...
ca me laisse 2^4 x 3 fonctions à établir, et vu que tout est indexé sous
forme d'entier, la surdéfinitions des méthodes ne donne meme pas de
solutions confortable et pratique... Je n'ai pas trop envie de manipuler
des tonnes de test en if then else et des tableaux et masques non plus
car c'est une méthode très fréquemment appelée...

Quelqu'un peut il me proposer une instruction SQL qui fournirait un code
élégant simple et efficace ?

Merci !

4 réponses

Avatar
Antoun
Pif wrote:
Bonjour, je suis en Java/MySQL.
J'ai une table qui contient des relations entre éléments, et ces
relations peuvent avoir des attributs (actuellement 4, ...)

id1, id2, attr_rel1, attr_rel2, attr_rel3, attr_rel4, ...

Je voudrais créer une méthode Java qui me liste les relations, en
spécifiant parfois le premier id, parfois le second (c'est pas pareil,
mes relations peuvent être orientées), parfois les deux, et en
choisissant parfois de retreindre suivant plusieurs critères (1 à 4)...
ca me laisse 2^4 x 3 fonctions à établir, et vu que tout est indexé sous
forme d'entier, la surdéfinitions des méthodes ne donne meme pas de
solutions confortable et pratique... Je n'ai pas trop envie de manipuler
des tonnes de test en if then else et des tableaux et masques non plus
car c'est une méthode très fréquemment appelée...

Quelqu'un peut il me proposer une instruction SQL qui fournirait un code
élégant simple et efficace ?

Merci !




ta méthode doit prendre en argument un tableau/hash de ce genre-là (en
syntaxe PHP, je ne connais pas le Java) :

Ex 1. les relations de l'élément 4 vers l'élément 2 avec 1 comme second
attribut : array('id1' => 4, 'id2' =>2, 'attr_rel2' => 1)

Ex 2. les relations pointant vers l'élément 6 avec 7 comme quatrième
attribut : array('id2' => 6, 'attr_rel4' => 7)

Ta méthode crée un tableau de chaînes, dont la taille est la même que
celle du tableau-argument.

Ta méthode contient une boucle qui analyse chaque couple clé/valeur du
tableau fourni. Chacun de ces couples te fournit une chaîne "Clé =
Valeur", que tu stockes dans le tableau de chaînes.

A l'issue de la boucles, tu joins les éléments du tableaux de chaînes en
les séparant par un " AND ", et tu concatènes le tout derrière le début
de ta requête SQL... Toujours en syntaxe PHP :
$sql = 'SELECT * FROM table WHERE ' . join(' AND ', $tablo_chaines) ;

à la fin, tu récupères un code SQL de ce genre-là :

Ex 1. SELECT * FROM table WHERE id1 = 4 AND id2 = 2 AND attr_rel2 = 1
Ex 2. SELECT * FROM table WHERE id2 = 6 AND attr_rel4 = 7

Ai-je bien compris ton problème ?
Avatar
Pif
à la fin, tu récupères un code SQL de ce genre-là :

Ex 1. SELECT * FROM table WHERE id1 = 4 AND id2 = 2 AND attr_rel2 = 1
Ex 2. SELECT * FROM table WHERE id2 = 6 AND attr_rel4 = 7

Ai-je bien compris ton problème ?



pas tout a fait, si on regarde le code SQL final, tu as combien de
requettes possibles 2^(2+nbcrit), dans mon ca je suis déjà à 64
requetes... et des problèmes de langage...

si je veux réduire le nombre de requetes différentes dans mon code j'ai
deux solutions :
- des if un peu partout dans une grosse méthode, et composer la requete
durant l'executions
- trouver une requete plus générique en SQL ou une manipulation du
Statement qui permette de créer la requette à l'initialisation et ne
faire que la relancer avec des parametres différentes...

la premiere me pose des soucis d'efficacité, si quelqu'un a une
proposition dans le deuxieme cas...
Avatar
Antoun
Pif wrote:

à la fin, tu récupères un code SQL de ce genre-là :

Ex 1. SELECT * FROM table WHERE id1 = 4 AND id2 = 2 AND attr_rel2 = 1
Ex 2. SELECT * FROM table WHERE id2 = 6 AND attr_rel4 = 7

Ai-je bien compris ton problème ?




pas tout a fait, si on regarde le code SQL final, tu as combien de
requettes possibles 2^(2+nbcrit), dans mon ca je suis déjà à 64
requetes... et des problèmes de langage...

si je veux réduire le nombre de requetes différentes dans mon code j'ai
deux solutions :
- des if un peu partout dans une grosse méthode, et composer la requete
durant l'executions
- trouver une requete plus générique en SQL ou une manipulation du
Statement qui permette de créer la requette à l'initialisation et ne
faire que la relancer avec des parametres différentes...

la premiere me pose des soucis d'efficacité, si quelqu'un a une
proposition dans le deuxieme cas...



En fait, ce que tu veux c'est un _prepared statement_ que tu puisses
utiliser quel que soit le nombre de critères effectivement transmis ?

Si je nomme $1, $2... $6 tes critères, et que je suppose que tu
transmets un NULL quand tu ne veux pas utiliser un critère, que
dirais-tu de ça ?

SELECT *
FROM table
WHERE (id1 = $1 OR $1 IS NULL)
AND (id2 = $2 OR $2 IS NULL)
AND (attr_rel1 = $3 OR $3 IS NULL)
AND (attr_rel2 = $4 OR $4 IS NULL)
AND (attr_rel3 = $5 OR $5 IS NULL)
AND (attr_rel4 = $6 OR $6 IS NULL)

Comme tu es en MySQL, tu peux aussi utiliser une syntaxe spécifique qui
présente l'avantage de ne pas répéter les $1, $2...:

...
WHERE id1 = IFNULL($1, id1)
AND id2 = IFNULL($2, id2)
AND ...
Avatar
Pif
en fait, je suis désolé de te recontredire, mais pour ce que j'y avais
réfléchi, j'avais conclu qu'il y avait une différente :

si je fait une recherche avec id1= $1 or $1 is null, ca va me retourner
tous les enregistrements qui n'ont pas d'identifiant ou un identifiant
égal à la valeur que j'indique

c'est différent de ce que je recherche, c'est à dire faire disparaitre
cette clause du where...

notamment pasque mon id1 et id2 de types "not null"... un relation
concerne forcément deux éléments dans mon schéma... le fait de regarder
indifféremment les identifiant est pourtant souhaitable (par exemple
connaitre tous les voisins gauches du sommet id2.

ok ?

merci.


que dirais-tu de ça ?

SELECT *
FROM table
WHERE (id1 = $1 OR $1 IS NULL)
AND (id2 = $2 OR $2 IS NULL)
AND (attr_rel1 = $3 OR $3 IS NULL)
AND (attr_rel2 = $4 OR $4 IS NULL)
AND (attr_rel3 = $5 OR $5 IS NULL)
AND (attr_rel4 = $6 OR $6 IS NULL)

Comme tu es en MySQL, tu peux aussi utiliser une syntaxe spécifique qui
présente l'avantage de ne pas répéter les $1, $2...:

...
WHERE id1 = IFNULL($1, id1)
AND id2 = IFNULL($2, id2)
AND ...