Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1338 connectés 

  FORUM HardWare.fr
  Programmation

  sql: multiselect en un seul...

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

sql: multiselect en un seul...

n°22222
wouatouwou​atou
Posté le 04-04-2001 à 10:38:58  profilanswer
 

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:

mood
Publicité
Posté le 04-04-2001 à 10:38:58  profilanswer
 

n°22234
thegti
La constipation se soigne ...
Posté le 04-04-2001 à 11:18:30  profilanswer
 

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

n°22238
Fred999
Rabat-joie
Posté le 04-04-2001 à 11:22:20  profilanswer
 

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?

n°22239
Roswell_
Posté le 04-04-2001 à 11:25:41  profilanswer
 

La solution doit être avec CONNECT BY toto un truc du genre.


---------------
http://www.cheata.net le site qui vous donne la banane!
n°22240
wouatouwou​atou
Posté le 04-04-2001 à 11:32:31  profilanswer
 

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)
)

n°22242
wouatouwou​atou
Posté le 04-04-2001 à 11:37:11  profilanswer
 

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 :(

n°22243
Fred999
Rabat-joie
Posté le 04-04-2001 à 11:39:25  profilanswer
 

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]

n°22247
wouatouwou​atou
Posté le 04-04-2001 à 11:50:37  profilanswer
 

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:

n°22251
Fred999
Rabat-joie
Posté le 04-04-2001 à 11:57:13  profilanswer
 

OK j'ai (enfin) compris. Et, effectivement, c'est un truc récursif.

n°22252
Fred999
Rabat-joie
Posté le 04-04-2001 à 12:02:36  profilanswer
 

Je te donne une méthode, je pense avoir trouvé.
 
10 minutes le temps que je ponde le script.

mood
Publicité
Posté le 04-04-2001 à 12:02:36  profilanswer
 

n°22255
Fred999
Rabat-joie
Posté le 04-04-2001 à 12:06:15  profilanswer
 

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]

n°22256
wouatouwou​atou
Posté le 04-04-2001 à 12:18:25  profilanswer
 

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:

n°22259
wouatouwou​atou
Posté le 04-04-2001 à 12:24:04  profilanswer
 

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

n°22277
irulan
Posté le 04-04-2001 à 14:04:30  profilanswer
 

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]

n°22280
Fred999
Rabat-joie
Posté le 04-04-2001 à 14:11:34  profilanswer
 

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]

n°22294
wouatouwou​atou
Posté le 04-04-2001 à 15:16:14  profilanswer
 

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]

n°22296
Fred999
Rabat-joie
Posté le 04-04-2001 à 15:29:47  profilanswer
 

[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)

n°22312
wouatouwou​atou
Posté le 04-04-2001 à 15:47:57  profilanswer
 

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  
 

n°22313
Fred999
Rabat-joie
Posté le 04-04-2001 à 15:54:09  profilanswer
 

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 ;)

n°22316
wouatouwou​atou
Posté le 04-04-2001 à 16:09:41  profilanswer
 

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.

n°22318
Fred999
Rabat-joie
Posté le 04-04-2001 à 16:14:29  profilanswer
 

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...

n°22320
wouatouwou​atou
Posté le 04-04-2001 à 16:19:50  profilanswer
 

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 ?

n°22323
Fred999
Rabat-joie
Posté le 04-04-2001 à 16:29:10  profilanswer
 

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é.

n°22327
wouatouwou​atou
Posté le 04-04-2001 à 16:33:26  profilanswer
 

ps pour proc. stock. :D
Désolé, ce sont mes abreviations...

 

[edit]--Message édité par wouatouwouatou--[/edit]

n°22330
Fred999
Rabat-joie
Posté le 04-04-2001 à 16:40:48  profilanswer
 

Bin pour le mettre en proc stock... Tu n'as pas d'exemples de procs stockées à ton bureau? :??:

n°22332
wouatouwou​atou
Posté le 04-04-2001 à 16:42:16  profilanswer
 

si jai trouve merci :D

n°22336
wouatouwou​atou
Posté le 04-04-2001 à 16:49:01  profilanswer
 

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
 

n°22340
Fred999
Rabat-joie
Posté le 04-04-2001 à 16:57:48  profilanswer
 

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!

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation

  sql: multiselect en un seul...

 

Sujets relatifs
Plus de sujets relatifs à : sql: multiselect en un seul...


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR