| |||||
| Dernière réponse | |
|---|---|
| Sujet : sql: multiselect en un seul... | |
| Fred999 | Pas de problème. C'était quand même assez tordu ton truc, on ne me l'avait jamais fait faire, j'aurai au moins appris quelque chose aujourd'hui! |
| Aperçu |
|---|
| Vue Rapide de la discussion |
|---|
| Fred999 | Pas de problème. C'était quand même assez tordu ton truc, on ne me l'avait jamais fait faire, j'aurai au moins appris quelque chose aujourd'hui! |
| wouatouwouatou | Super ca marche impec ton script...
Un grand MERCI !! :jap::jap::jap::jap::jap::jap::jap::jap::jap::jap::jap::jap::jap: P.S: voila le script final: (en transac.. désolé.. mais bon il marche :D ) drop table toto GO create table toto ( a numeric(10) identity primary key, b numeric(10), c varchar(20), constraint fk_toto_toto foreign key (b) references toto(a) ) GO drop procedure sp_test_toto go create procedure sp_test_toto @tete numeric(10) as begin create table #tmp_toto ( a numeric(10), b numeric(10), c varchar(20), rang int ); declare @inCompteur int; declare @inRang int; select @inCompteur = 1, @inRang = 0 /* Insertion initiale */ insert #tmp_toto select a, b, c, @inRang from toto where a = @tete; /* Insertions récursives */ while ( @inCompteur != 0 ) begin insert #tmp_toto (a, b, c, rang) select t1.a, t1.b, t1.c, @inRang + 1 from toto t1, #tmp_toto t2 where t1.a = t2.b and t2.rang = @inRang select @inCompteur = @@rowcount select @inRang = @inRang + 1 end select * from #tmp_toto drop table #tmp_toto end go |
| wouatouwouatou | si jai trouve merci :D |
| Fred999 | Bin pour le mettre en proc stock... Tu n'as pas d'exemples de procs stockées à ton bureau? :??: |
| wouatouwouatou | ps pour proc. stock. :D
Désolé, ce sont mes abreviations... [edit]--Message édité par wouatouwouatou--[/edit] |
| Fred999 | Si, ta condition est bonne fonctionnellement parlant, mais la syntaxe laissait fortement à désirer.
"mettre en ps"?????? :??: Et si, il faut virer la table tempo. J'avais oublié. |
| wouatouwouatou | ouais... en clair, elle sert a rien cette condition donc... :D
merci... au fait comment tu fait pour le mettre en ps ? c koi la syntaxe ? Pi fo pas dropper la table tmp ? |
| Fred999 | OK... Deux manières différentes d'aborder le problème.
1. while (select count (*) from #tmp_toto where b is null and rang = @inRang - 1) = 0 C'est ce que tu veux faire : vérifier que toutes les lignes du rang max de la table #tmp_toto ne pointent sur rien : pas de suivantes. 2. While @inCompteur != 0 Tant qu'on trouve des lignes qui suivent... |
| wouatouwouatou | bah.. en fait, c la condition de sortie de la boucle :D
while ( #tmp_toto.b is not null ) do ... Car si la ligne trouvee ne pointe plus sur une ligne (donc b vaut null) alors i fo s'arreter la. |
| Fred999 | create table #tmp_toto (
a numeric(10), b numeric(10), c varchar(20), rang int ) declare @inCompteur int declare @inRang int select @inCompteur = 1, @inRang = 0 /* Insertion initiale */ insert #tmp_toto select a, b, c, @inRang from toto where a = 1 /* Insertions récursives */ while ( @inCompteur != 0 ) begin if ( #tmp_toto.b is null ) then exit; end if J'avais pas vu cette ligne :D if (#tmp_toto.b is null) Alors là... c'est du barbarisme!!! Si tu veux vérifier un champ de la table #tmp_toto, il faut que tu fasses un if exists(). Mais tu veux faire quoi exactement? ET LES AUTRES, VOUS Y AVEZ JETE UN OEIL AU SCRIPT? Sinon, pour le reste, ça m'a l'air OK. insert #tmp_toto (a, b, c, rang) select t1.a, t1.b, t1.c, @inRang + 1 from toto t1, #tmp_toto t2 where t1.a = t2.b and t2.rang = @inRang select @inCompteur = @@rowcount select @inRang = @inRang + 1 end select * from #tmp_toto Et à dans 10 minutes ;) |
| wouatouwouatou | bon... ok pour inRang..
la ligne d'origine , i me la fo aussi :) donc ok aussi. Pour la condition de sortie, tas raison... de toute maniere, il ne devrai y avoir kune seule ligne trouvee a la fois, du fait ke c la cle primaire. Et le if... dans la boucle devrai normalement faire une sorte de break; Quant a la syntaxe... moi, jsais pas... car mon pl/sql est aussi bon ke mon transac voire pire :D Donc apres tout ca je refait le script ki donne ( syntaxiquement fo :D ) : create table #tmp_toto ( a numeric(10), b numeric(10), c varchar(20), rang int ) declare @inCompteur int declare @inRang int select @inCompteur = 1, @inRang = 0 /* Insertion initiale */ insert #tmp_toto select a, b, c, @inRang from toto where a = 1 /* Insertions récursives */ while ( @inCompteur != 0 ) begin if ( #tmp_toto.b is null ) then exit; end if insert #tmp_toto (a, b, c, rang) select t1.a, t1.b, t1.c, @inRang + 1 from toto t1, #tmp_toto t2 where t1.a = t2.b and t2.rang = @inRang select @inCompteur = @@rowcount select @inRang = @inRang + 1 end select * from #tmp_toto |
| Fred999 | [citation][nom]wouatouwouatou a écrit[/nom]
create table #tmp_toto ( a numeric(10), b numeric(10), c varchar(20), rang int ) declare @inCompteur int declare @inRang int select @inCompteur = 1, @inRang = 0 /* Insertion initiale */ insert #tmp_toto select a, b, c, @inRang from toto where a = 1 Si tu veux la ligne d'origine, alors OK. Tu l'avais précisé? /* Insertions récursives */ while (@inRang < @inCompteur) begin select @inRang = @inRang + 1 Tu ne peux pas incrémenter le rang dès le début de la boucle... Au premier passage, tu n'auras que du rang 0 dans ta table tempo, et la requête va aller chercher les lignes de rang 1. Si j'avais fait un petit mic-mac sur l'incrémentation, ce n'était pas pour rien... Ou alors, le 2e critère du WHERE devient t2.rang = @inRang - 1 De plus, donner comme critère de sortie de boucle @inRang < @inCompteur me paraît plus que douteux. Tu peux justifier? if ( #tmp_toto.b is not null ) then insert #tmp_toto (a, b, c, rang) select t1.a, t1.b, t1.c, @inRang from toto t1, #tmp_toto t2 where t1.a = t2.b and t2.rang = @inRang select count(*) into @inCompteur from #tmp_toto La syntaxe PL-SQL n'est-clle pas select @inCompteur := count (*) ... ? end if end select * from #tmp_toto Bon, après, tu mets ça en proc stock, tu compiles, et tu exécutes avec la commande @@nom_proc (si mes souvenirs sont bons) |
| wouatouwouatou | Fred999> j'ai retouché un peu ton script... je pense ke kom ca il fait un peu mie ce e je veux... mais si tu (ou kkun) pouvais corriger ce serait cool... paske moi jsuis assez mediocre en sql :)
create table #tmp_toto ( a numeric(10), b numeric(10), c varchar(20), rang int ) declare @inCompteur int declare @inRang int select @inCompteur = 1, @inRang = 0 /* Insertion initiale */ insert #tmp_toto select a, b, c, @inRang from toto where a = 1 /* Insertions récursives */ while (@inRang < @inCompteur) begin select @inRang = @inRang + 1 if ( #tmp_toto.b is not null ) then insert #tmp_toto (a, b, c, rang) select t1.a, t1.b, t1.c, @inRang from toto t1, #tmp_toto t2 where t1.a = t2.b and t2.rang = @inRang select count(*) into @inCompteur end if from #tmp_toto end select * from #tmp_toto Mais jsais toujours pas komment le transformer en pl/sql... Mes souvenirs dans ce domaine me font defaut :D Alors, si une ame charitable pouvait... :jap: p.s: Comment kon fait pour mettre ce truc en proc. stock. et l'utiliser apres ? [edit]--Message édité par wouatouwouatou--[/edit] |
| Fred999 | Effectivement, il te faut une procédure stockée.
Bon, la traduction en PL-SQL ne doit pas poser de problème, simplement, PL-SQL préfère les curseurs aux tables tempo. Mais bon, dans ton cas, ça devrait tout de même le faire... Juste un truc : Les variables en Transact-SQL sont toujours préfixées par : - @ pour les variables utilisateur (@inCompteur et @inRang ici) - @@ pour les variables système : @@rowcount représente le nombre de lignes ramenées par la dernière requête exécutée (ici, l'insert : quand @@rowcount = 0, c'est qu'on n'a effectué aucune insertion). Et les tables temporaires sont toujours préfixées par #. Voilà, tu devrais pouvoir te débrouiller avec ça non? Si tu n'as pas compris l'algo, demande... [edit]--Message édité par Fred999--[/edit] |
| irulan | Je pense qu'en PL/SQL sous Oracle 8 ça devrait pouvoir se faire (c'est une procédure stockée là aussi) [edit]--Message édité par Irulan--[/edit] |
| wouatouwouatou | Merci pour ton script Fred999... meme si j'y comprend pas grd chose.
Mais bon, si jai bien compris il fodrait ke je mette ca dans une procedure stockee si je veux l'utiliser, non ? En fait, jai donne un script pour sqlserver paske plus rapide a ecrire... Mais en fait il me fodrait une solution pour oracle 8. :D |
| wouatouwouatou | je viens de revoir ma problematique, (kel mot :D )
En fait, on peut resumer ca en faisant une analogie avec un ensemble de listes chainees. Donc en fait, ma table toto serait en qq sorte un ensemble de listes chainees. Et moi je veux une liste entiere connaissant la tete. En clair je veux une liste particuliere dans l'ensemble de liste :D. Je crois ke c un peu tordu kom truc mais bon... :sarcastic: |
| Fred999 | Tu peux faire un truc du genre :
create table #tmp_toto ( a numeric(10), b numeric(10), c varchar(20), rang int ) declare @inCompteur int declare @inRang int select @inCompteur = 1, @inRang = 0 /* Insertion initiale */ insert #tmp_toto select t2.a, t2.b, t2.c, @inRang from toto t1, toto t2 where t1.a = 1 and t1.a = t2.b /* Insertions récursives */ while (@inCompteur != 0) begin insert #tmp_toto (a, b, c, rang) select t1.a, t1.b, t1.c, @inRang + 1 from toto t1, #tmp_toto t2 where t1.b = t2.a and t2.rang = @inRang select @inCompteur = @@rowcount select @inRang = @inRang + 1 end select * from #tmp_toto Bon, l'insertion initiale te donne les lignes qui sont directement reliées de premier niveau. Et, ensuite, on insère les lignes reliées aux lignes du niveau donné, de manière récursive ; quand on n'en trouve plus, on sort de la boucle. Le souci, c'est que si tu t'emmèles les pinceaux au momoent de l'insertion, tu risques de tourner en rond : prévoir, donc, une porte de sortie (par exemple, au niveau 50, il doit commencer à y avoir un gros souci...). Bon, j'utilise une table temporaire, ça me paraît adapté à la situation, et c'est bien dans l'esprit de SQL Server (qui n'aime pas trop les curseurs...) ATTENTION!!! J'avais fait une couille dans l'initialisation des variables et la condition de sortie de la boucle. C'est corrigé. [edit]--Message édité par Fred999--[/edit] |
| Fred999 | Je te donne une méthode, je pense avoir trouvé.
10 minutes le temps que je ponde le script. |
| Fred999 | OK j'ai (enfin) compris. Et, effectivement, c'est un truc récursif. |
| wouatouwouatou | Fred999> J'y avais pensé, mais de cette manière, on n'obtient que les lignes liées d'un nivo. seulement.
Moi il me fodrait tous les nivos: c.a.d la ligne ki est donnee par b ainsi ke celle ki est eventuellement donnee ar cette derniere, pi etc.... En fait, je pense ke le pb. est un truc recursif. Mais comment le resoudre... :??: thegti> tu pourrais pas me faire le script avec les cuseur... :D paske moi jy connais kedal (enfin, pas grd chose) en curseur. :jap: |
| Fred999 | A priori, je te proposerais ça :
select t2.* from toto t1, toto t2 where t1.a = t2.b and t1.a = 1 [edit]--Message édité par Fred999--[/edit] |
| wouatouwouatou | bah.. c pour mon histoire de jointure.
Tu sais les jointure du genre: A.1=B.1 AND B.2=C.2 AND C.3=D.2 AND etc... Enfin, bref... Un chtit exemple de script plz... jsuis un peu perdu la :( |
| wouatouwouatou | voila un script sous sql server... enfin, a ma sauce :D
create table toto ( a numeric(10) IDENTITY PRIMARY KEY, b numeric(10), c varchar(20), constraint FK_toto_toto foreign key (b) references toto(a) ) |
| Roswell_ | La solution doit être avec CONNECT BY toto un truc du genre. |
| Fred999 | Je ne comprends pas. b référence la PK de toto, soit a?????
Tu peux nous mettre un pseudo-script de création de table? |
| thegti | lut
C'est bizarre ta clé étrangère sur la même table (jamais vu un truc pareil !) Et la récursivité n'est pas gérable sous SQL. Transact SQL ou PL/SQL avec des boucles ca doit le faire |
| wouatouwouatou | J'ai un table toto de trois colonnes a,b,c.
a etant la cle primaire. b est une cle etrangere referencant toto c est une colonne de valeurs... Bon, voila le pb.: Est-il possible d'obtenir toutes les lignes dépendant d'une ligne connue. Par exemple, je veux toutes les lignes liées a la ligne dont la colonne a vaut 1 (En supposant kil ny aura pas de recursivité sans fin avec les valeurs entre a et b) Bien sur, la colonne b peut 'pointer' sur une ligne ki elle meme pointe sur une autre, etc... Merci pour les reponses... :jap: |




