Défi pour trouver une requête complexe [ASP - Sql Server 2000] - SQL/NoSQL - Programmation
Marsh Posté le 26-10-2005 à 09:47:40
J'ai pas trop le temps.
Déjà, c'est Windows 2000 ou 2003 et SQL Server 2000 ou 2005, mais pas SQL Server 2003 .
Sinon, j'ai vraiment pas le temps de lire en détail.
Pour moi, fais une fonction récursive (en T-SQL) qui permet, pour une ligne, d'aller voir si ça répond au mot clé, et se relance pour chaque granule liée. (et vu que c'est récursif, ça ira jusqu'au bout de la branche).
Seule limitation, la récursivité avec SQL Server 2000 (2005, je sais pas), c'est que ça n'accepte pas plus de 20 niveaux de profondeur (mais je doute que tu aies des sous-sous-sous...sous-granules sur 20 niveaux )
Ca te permettra de faire une requête très simple, tout en conservant des performances honnêtes, et en étant sûr de supporter tous les cas (y compris le sous-sous-granules), et avec une seule connection à SQL Server (donc infiniment mieu que X requêtes dans tes boucles, aussi optimisées soient-elles)
Marsh Posté le 26-10-2005 à 09:48:51
ps: quand je lis le contenu de ta table, je ne comprends pas comment tu gères la relation père/fils
Marsh Posté le 26-10-2005 à 09:50:47
Après un coup d'oeil rapide, je crois comprendre qu'il s'agit d'un problème classique, où une ligne en sortie se base sur plusieurs lignes en entrée, et où il faut donc distinguer ces lignes avec des alias, par exemple D1 et D2. Ce qui done :
... |
Marsh Posté le 26-10-2005 à 09:59:51
Arjuna a écrit : ps: quand je lis le contenu de ta table, je ne comprends pas comment tu gères la relation père/fils |
Merci pour le coup du 2000/2003. C'est donc bien sqlServer 2000 sous windows server 2003.
Imaginons un manuel (qu'on appelle Manuel1) qui a 4 fils , Granule1, 2, 3 et 4 dans cet ordre
on va donc avoir (les colonnes sont Numero, NomDescripteur, Valeur, TypeValeur, Ordre)
1 Parent Manuel1 Granule 1 ...
2 Parent Manuel1 Granule 2 ...
3 Parent Manuel1 Granule 3 ...
4 Parent Manuel1 Granule 4 ...
En fait tout se fait au niveau de l'enfant, et non du parent.
Je vais tester le coup des alias...
Marsh Posté le 26-10-2005 à 11:08:17
Bon, ben les alias, dans l'état, ça fonctionne pas.
La je vais tenter autre chose : fonctionner avec des vues successives. A savoir une vue pour chaque champ de recherche... Et le suivant cherche dans la vue, et ainsi de suite...
Ca remplacera peut-être le INTERSECT.
Franchement, ce INTERSECT me paraît être une notion fondamentale, et au final, il n'est pas reconnu comme standard sql. Je trouve ça vraiment débile. C'est LE truc opposé à l'UNION, ça me paraît plutôt important mais bon...
Marsh Posté le 26-10-2005 à 11:54:00
Bon, ben j'ai trouvé la solution.
C'était plutôt simple en fait.
Pour simuler l'INTERSECT j'ai utilisé IN
Dim RequeteTemp, premierdesc, closeparenthese |
Donc, voici la requete si je fais une recherche avec les critères :
Auteur LIKE 'ben'
Sujet LIKE '1'
SELECT DISTINCT Numero
FROM Descripteur_Valeur
WHERE TypeValeur = 'Granule'
AND Valide = 1
AND Numero IN
(SELECT Numero
FROM Descripteur_Valeur
WHERE Valide = 1
AND TypeValeur = 'Granule'
AND NomDescripteur LIKE '%Auteur%' AND (Valeur LIKE '%ben%' ))
AND Numero IN
(SELECT Numero
FROM Descripteur_Valeur
WHERE Valide = 1
AND TypeValeur = 'Granule'
AND NomDescripteur LIKE '%Sujet%' AND (Valeur LIKE '%1%' ))
Et ainsi, mes clauses AND Numero IN s'ajoutent, et les résulats sont pour l'instant tous corrects.
Merci en tout cas de votre aide.
Est-ce que quelqu'un sait, au passage, pourquoi le INTERSECT ne fait-il pas partie de la norme SQL ?
Je veux dire, on l'apprend à l'école au même titre que l'UNION comme une opération VALIDE sur les ensembles.
Le produit, la division, l'union, l'intersection... J'invente rien !
Bref, ya une explication ?
Marsh Posté le 26-10-2005 à 09:27:08
Bonjour,
Bon, je soumets mon problème dans un topic, parce que là, je m'enlise en fait.
J'explique (Je travaille en ASP donc, avec SqlServer 2000 derrière, serveur IIS évidemment).
J'ai une table dans ma bd, qui s'appelle Descripteur_Valeur. Elle sert à décrire deux types d'entités, les Granules et Manuels. Les manuels peuvent être composés de granules et des manuels, et les granules peuvent être composés de granules (des sous-granules en fait, mais pour le code, c'est la même chose).
Elle a la structure suivante :
Descripteur_Valeur
Numero (Le numero du granule ou du manuel)
NomDescripteur (ben ça peut être Titre, Sujet, Date de création, Mots-Clefs, etc, etc)
Valeur (La valeur du descripteur donc)
TypeValeur (Indique s'il s'agit d'un Granule ou d'un Manuel, il peut donc prendre deux valeurs, Granule ou Manuel)
Ordre (Ne sert que pour le descripteur Parent...)
Valide (pour savoir si un granule ou manuel est en cours de création, et s'il a été validé ou non... Il n'apparaît à l'user final que s'il a ce champ à 1)
Obligatoire(Il y a quelques descripteurs obligatoires : Titre, Sujet, Date de création, Mots-Clefs, n° Version, les autres sont facultatifs)
Je dois faire une recherche avec des champs personnalisés, uniquement sur cette table.
Voici un aperçu (non trié du contenu de ma table, les colonnes dans l'ordre indiqué plus haut.
1 Auteur Benjamin GRISTI Granule 0 1 1
1 Auteur Benjamin GRISTI Manuel 0 1 1
1 Date de création 21/10/2005 16:07:10 Granule 0 1 1
1 Date de création 21/10/2005 16:28:13 Manuel 0 1 1
1 Dernière modific.. 21/10/2005 16:28:59 Manuel 0 0 1
1 Mots-Clefs au revoir Granule 0 1 1
1 Mots-Clefs beta version Manuel 0 1 1
1 Mots-Clefs bonjour Granule 0 1 1
1 Mots-Clefs bonjour Manuel 0 1 1
1 Mots-Clefs essai Manuel 0 1 1
1 Mots-Clefs joli Granule 0 1 1
1 Mots-Clefs nouveau Granule 0 1 1
Voici un screenshot de ma page de recherche :
Donc ma recherche permet d'ajouter des champs de recherche, en fonction de ceux existant dans la base (dans mon exemple, il n'y a que des champs obligatoires, mais la recherche sera permis sur tous les Descripteurs existant dans la base.
Le + dans un champ de recherche permet la recherche de plusieurs valeurs d'un descripteur (1+2 dans le champ numéro permet de rechercher le granule 1 et le granule 2).
Ah au fait, la recherche, ici, ne concerne que les granules.
Voici donc, en asp, mon code permettant de générer la requete...
'Recupérer le tableau avec les champs de recherche rajoutés
TabDesc = Split(PreparePourBdd(Request.Form("listnewdesc" )), "," )
NbDesc = UBound(TabDesc)
'Le champ mots-clefs
TabMots = Split(Trim(MotsClefs), "+" )
NbMots = UBound(TabMots)
'Le champ numéro
TabNum = Split(Trim(Numero), "+" )
NbNum = UBound(TabNum)
'La requete de base
Requete = _
"SELECT DISTINCT Numero " & _
"FROM Descripteur_Valeur " & _
"WHERE TypeValeur = 'Granule' " & _
"AND Valide = 1 "
'############# RECHERCHE DES NUMEROS DE GRANULES ####################
premiereligne = True
For i = 0 To NbNum
If TabNum(i) <> "" Then
If premiereligne Then
Requete = Requete & _
"AND (Numero = " & TabNum(i) & " "
premiereligne = False
Else
Requete = Requete & _
"OR Numero = " & TabNum(i) & " "
End If
End If
Next
If Numero <> "" Then
Requete = Requete & " ) "
End If
premiereligne = True
'Et c'est sur la suite que ça bugue...
'############# RECHERCHE DE DESCRIPTEURS FACULTATIFS ####################
Dim RequeteTemp, premierdesc
RequeteTemp = Requete
premierdesc = True
Response.Write "<br>###########################<br>"
Response.Write Requete
Response.Write "<br>###########################<br>"
For i = 0 To NbDesc
If TabDesc(i) <> "" Then
TabTempDesc = Split(Request.Form("Desc_" & TabDesc(i)), "+" )
NbTempDesc = UBound(TabTempDesc)
If TabDesc(i) <> "" Then
If premierdesc Then
Requete = RequeteTemp & _
"AND (NomDescripteur LIKE '%" & Replace(TabDesc(i),"#/", " " ) & "%' "
premierdesc = False
Else
Requete = RequeteTemp & _
"AND EXISTS ( " & _
"SELECT * " & _
"FROM Descripteur_Valeur " & _
"WHERE Valide = 1 " & _
"AND TypeValeur = 'Granule' " & _
"AND (NomDescripteur LIKE '%" & Replace(TabDesc(i),"#/", " " ) & "%' "
End If
End If
For j = 0 To NbTempDesc
If premiereligne Then
Requete = Requete & _
"AND (Valeur LIKE '%" & TabTempDesc(j) & "%' "
premiereligne = False
Else
Requete = Requete & _
"OR Valeur LIKE '%" & TabTempDesc(j) & "%' "
End If
Next
If TabDesc(i) <> "" Then
Requete = Requete & " ) "
End If
Requete = Requete & " )"
End If
'premierdesc = True
premiereligne = True
Next
Pour la requête INTERSECT aurait très bien fonctionné. Manque de pot, ça ne marche pas sous SqlServer. J'ai donc essayé le WHERE EXISTS, mais ça ne convient pas, les champs de recherche n'ayant pas d'ordre, le where exists se base sur le resultat de la requete qui le précède, et selon l'ordre, les résultats changent. Donc c'est mort.
Je dois impérativement trouver un moyen de faire cette recherche, détourné, ou bourrin même, sale, propre, peu importe, mais il le faut (et en plus il le faut avant mercredi prochain...)
Bref, si quelqu'un a le temps de s'atteler à mon problème, ça m'enleverai la tour eiffel qui est coincée dans mon petit orteil...
Merci d'avance.
Message édité par backdafuckup le 26-10-2005 à 09:53:02