OVH Cloud OVH Cloud

Transformer une table

19 réponses
Avatar
moromain
Bonjour,

J'ai une table avec plusieurs champs C1, C2, C3 :
- C1 est l'iD de chaque enregistrement,
- C2 contient le nom de l'enregistrement,
- C3 renvoi =E0 un iD, appel=E9 "p=E8re".
Elle se pr=E9sente de la mani=E8re suivante :
C1 C2 C3
1 A
2 AG 1
3 AK 1
4 AGY 2
5 AGH 2
6 B
7 BC 6
8 BCJ 7
Le champs C3 permet de hi=E9rarchiser les donn=E9es.
Mon objectif est de transformer cette table est une table de la forme
suivante :
A
A AG
A AG AGY
A AG AGH
A AK
B
B BC
B BC BCJ
Cette forme est plus visuelle : un coups d'oeil permet de comprendre
la hi=E9rarchie.
Vous devinez ma question : je n'y arrive pas !!!
J'ai essay=E9 en cr=E9ant des requ=EAtes qui contiennent par exemple
(A,B...), (AG, AK, BC...)... J'ai 13 niveaux hi=E9rarchiques. Les 13
niveaux ne sont pas toujours remplis.
Une id=E9e ?

9 réponses

1 2
Avatar
moromain
Eureka !
J'ai trouvé. J'ai fait une requête dans laquelle les 13 champs sont
sélectionnés par une fonction.
Ca marche mais c'est très lourd, donc lent...
Je vous la présenterai demain...
Avatar
Michel_D
Eureka !
J'ai trouvé. J'ai fait une requête dans laquelle les 13 champs sont
sélectionnés par une fonction.
Ca marche mais c'est très lourd, donc lent...
Je vous la présenterai demain...


Regarde si la requète suivante te donne le résultat voulu :

SELECT c2 AS Nv1, Null AS Nv2, Null AS Nv3
FROM T
WHERE (c3 Is Null)
UNION SELECT N1.c2, N2.c2, Null
FROM T AS N1 INNER JOIN T AS N2 ON N1.c1=N2.c3
WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null)
UNION SELECT N1.c2, N2.c2, N3.c2
FROM T AS N1 INNER JOIN (T AS N2 INNER JOIN T AS N3
ON N2.c1=N3.c3) ON N1.c1=N2.c3
WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null) And (N3.c3 Is Not Null);

Avatar
moromain
Pour Michel_D :
Ca marche ! C'est plus simple que ma solution.
Je vais regarder pour la transposer avec 13 champs.
Merci en tout cas !

Ma solution :
Dans ma base, j'ai un champs dans lequel j'indique le niveau
hiérarchique de chaque enregistrement (j'ai mis des code en lettres).
Appelons-le champs C4.
J'ai créé une requête, avec un champs par niveau hiérarchique, plus un
dernier contenant le champs C1 (j'ai donc 14 champs).

Chaque champs est rempli par une fonction :
NiveauHierarchique1: TrouveNiveauhierarchique([C1];"CodeNiveau"), où
CodeNiveau correspond au code entré en C4.

Et la fonction :

Function CodeRequete(Insert As Double) As String
CodeRequete = "SELECT C1, C2, C3, C4 from maTable WHERE
((maTable.C1)="
CodeRequete = CodeRequete & Insert
CodeRequete = CodeRequete & ");"
End Function

Function TrouveNiveauhierarchique(NumEnrg As Double,
NiveauHierarchique As String) As String
Dim Continuer As Boolean
Dim rs As DAO.Recordset
Dim dbs As Database
Dim CodeNiveau, VieuxCodeNiveau As String

Set dbs = CurrentDb
Set rs = dbs.OpenRecordset(CodeRequete(NumEnrg))
CodeNiveau = rs!Code_Niveau
VieuxCodeNiveau = CodeNiveau
TrouveNiveauhierarchique= rs!C2 'Cas pour le niveau "0"
Continuer = True
If CodeNiveau = NiveauHierarchique Then Continuer = False
While Continuer = True
If IsNull(rs!C3) Then
TrouveNiveauhierarchique = ""
Continuer = False
Else
NumEnrg = rs!C3
Set rs = dbs.OpenRecordset(CodeRequete(NumEnrg))
CodeNiveau = rs!Code_Niveau
TrouveNiveauhierarchique = rs!C2
End If
If CodeNiveau = Niveauhierarchique Then Continuer = False
Wend
rs.Close
dbs.Close
End Function

L'opération est longue (j'ai 3700 enregistrements !). La solution de
Michel est quasiment instantanée, contrairement à la mienne !
Avatar
Michel_D
Dés l'instant que tu as compris le principe pour 3 champs (niveaux),
il te sera facile d'étendre la requête avec 13 champs (niveaux)
(bon ce sera un peu plus long à écrire; quoique avec le copier coller).


"moromain" a écrit dans le message de news:
Pour Michel_D :
Ca marche ! C'est plus simple que ma solution.
Je vais regarder pour la transposer avec 13 champs.
Merci en tout cas !

Ma solution :
Dans ma base, j'ai un champs dans lequel j'indique le niveau
hiérarchique de chaque enregistrement (j'ai mis des code en lettres).
Appelons-le champs C4.
J'ai créé une requête, avec un champs par niveau hiérarchique, plus un
dernier contenant le champs C1 (j'ai donc 14 champs).

Chaque champs est rempli par une fonction :
NiveauHierarchique1: TrouveNiveauhierarchique([C1];"CodeNiveau"), où
CodeNiveau correspond au code entré en C4.

Et la fonction :

Function CodeRequete(Insert As Double) As String
CodeRequete = "SELECT C1, C2, C3, C4 from maTable WHERE
((maTable.C1)="
CodeRequete = CodeRequete & Insert
CodeRequete = CodeRequete & ");"
End Function

Function TrouveNiveauhierarchique(NumEnrg As Double,
NiveauHierarchique As String) As String
Dim Continuer As Boolean
Dim rs As DAO.Recordset
Dim dbs As Database
Dim CodeNiveau, VieuxCodeNiveau As String

Set dbs = CurrentDb
Set rs = dbs.OpenRecordset(CodeRequete(NumEnrg))
CodeNiveau = rs!Code_Niveau
VieuxCodeNiveau = CodeNiveau
TrouveNiveauhierarchique= rs!C2 'Cas pour le niveau "0"
Continuer = True
If CodeNiveau = NiveauHierarchique Then Continuer = False
While Continuer = True
If IsNull(rs!C3) Then
TrouveNiveauhierarchique = ""
Continuer = False
Else
NumEnrg = rs!C3
Set rs = dbs.OpenRecordset(CodeRequete(NumEnrg))
CodeNiveau = rs!Code_Niveau
TrouveNiveauhierarchique = rs!C2
End If
If CodeNiveau = Niveauhierarchique Then Continuer = False
Wend
rs.Close
dbs.Close
End Function

L'opération est longue (j'ai 3700 enregistrements !). La solution de
Michel est quasiment instantanée, contrairement à la mienne !
Avatar
moromain
Je ne comprends pas tout. Je ne connais pas bien le langage SQL.
Les N1, N2, N3 correspondent à quoi ? A Nv1, Nv2, Nv3 ??
___
SELECT c2 AS Nv1, Null AS Nv2, Null AS Nv3
FROM T
WHERE (c3 Is Null)
UNION SELECT N1.c2, N2.c2, Null
___
Ici, on référence quoi ?
Si C3 est null, on parle alors du niveau hiérarchique le plus haut ?

______
FROM T AS N1 INNER JOIN T AS N2 ON N1.c1=N2.c3
on recherche les niveaux "père".




WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null)
Là je comprends pas !A quoi correspondent les Nx.Cy ???




UNION SELECT N1.c2, N2.c2, N3.c2
FROM T AS N1 INNER JOIN (T AS N2 INNER JOIN T AS N3
ON N2.c1=N3.c3) ON N1.c1=N2.c3
WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null) And (N3.c3 Is Not Null);



Avatar
Fabien
Bon ben je vois que j'avance pas trés vite ;-)
Tantpis .;;
Voici quant même ma solution
Public Sub change2()
Dim Db As DAO.Database
Dim Rst_source, Rst_sourceBis As DAO.Recordset
Dim I, Lg As Integer
Dim StrSql, StrSql_Cible, StrSql_Source As String
Set Db = CurrentDb
Set Rst_source = Db.OpenRecordset("Select * from [Source] where
nz([C3],0)=0")

While Not Rst_source.EOF
StrSql = "Insert Into Cible ([Champ1]) select '" &
Rst_source![c2] & "' as exp1;"
DoCmd.SetWarnings False
DoCmd.RunSQL StrSql ' On ajoute le 1 er element
DoCmd.SetWarnings True
change_reccurente "'" & Rst_source![c2] & "' as exp1,",
"[Champ1],", 1, Rst_source![C1]
Rst_source.MoveNext
Wend
Rst_source.Close
Set Rst_source = Nothing
Set Db = Nothing
End Sub
Public Sub change_reccurente(Chaine_source As Variant, chaine_cible As
Variant, Ordre As Integer, Num_Chainage As Integer)
Dim Db As DAO.Database
Dim Rst_source As DAO.Recordset
Dim I, Lg As Integer
Dim StrSql, StrSql_Cible, StrSql_Source As String
Set Db = CurrentDb
Set Rst_source = Db.OpenRecordset("Select * from Source where
[C3]='" & Num_Chainage & "'")
If Not Rst_source.EOF Then Ordre = Ordre + 1
While Not Rst_source.EOF
StrSql = "INSERT INTO Cible ("
StrSql_Source = Chaine_source
StrSql_Cible = chaine_cible
StrSql_Cible = StrSql_Cible & "[Champ" & Ordre & "], "
StrSql_Source = StrSql_Source & "'" & Rst_source![c2] & "' as
exp" & Ordre & ", "
change_reccurente StrSql_Source, StrSql_Cible, Ordre,
Rst_source![C1]
StrSql_Cible = Left(StrSql_Cible, Len(StrSql_Cible) - 2) & ")"
StrSql_Source = Left(StrSql_Source, Len(StrSql_Source) - 2)
StrSql = StrSql & StrSql_Cible & " "
StrSql = StrSql & "Select " & StrSql_Source & ";"
DoCmd.SetWarnings False
DoCmd.RunSQL StrSql
DoCmd.SetWarnings True

Rst_source.MoveNext
Wend
Rst_source.Close
Set Rst_source = Nothing
Set Db = Nothing
End Sub


Pour Michel_D :
Ca marche ! C'est plus simple que ma solution.
Je vais regarder pour la transposer avec 13 champs.
Merci en tout cas !

Ma solution :
Dans ma base, j'ai un champs dans lequel j'indique le niveau
hiérarchique de chaque enregistrement (j'ai mis des code en lettres).
Appelons-le champs C4.
J'ai créé une requête, avec un champs par niveau hiérarchique, plus un
dernier contenant le champs C1 (j'ai donc 14 champs).

Chaque champs est rempli par une fonction :
NiveauHierarchique1: TrouveNiveauhierarchique([C1];"CodeNiveau"), où
CodeNiveau correspond au code entré en C4.

Et la fonction :

Function CodeRequete(Insert As Double) As String
CodeRequete = "SELECT C1, C2, C3, C4 from maTable WHERE
((maTable.C1)="
CodeRequete = CodeRequete & Insert
CodeRequete = CodeRequete & ");"
End Function

Function TrouveNiveauhierarchique(NumEnrg As Double,
NiveauHierarchique As String) As String
Dim Continuer As Boolean
Dim rs As DAO.Recordset
Dim dbs As Database
Dim CodeNiveau, VieuxCodeNiveau As String

Set dbs = CurrentDb
Set rs = dbs.OpenRecordset(CodeRequete(NumEnrg))
CodeNiveau = rs!Code_Niveau
VieuxCodeNiveau = CodeNiveau
TrouveNiveauhierarchique= rs!C2 'Cas pour le niveau "0"
Continuer = True
If CodeNiveau = NiveauHierarchique Then Continuer = False
While Continuer = True
If IsNull(rs!C3) Then
TrouveNiveauhierarchique = ""
Continuer = False
Else
NumEnrg = rs!C3
Set rs = dbs.OpenRecordset(CodeRequete(NumEnrg))
CodeNiveau = rs!Code_Niveau
TrouveNiveauhierarchique = rs!C2
End If
If CodeNiveau = Niveauhierarchique Then Continuer = False
Wend
rs.Close
dbs.Close
End Function

L'opération est longue (j'ai 3700 enregistrements !). La solution de
Michel est quasiment instantanée, contrairement à la mienne !




Avatar
Michel_D
Bon déja il s'agit de décomposer le problème
La finalité de la requête permet d'unir le résultat de plusieurs
requête sélection qui traite en fait chaque champ (niveaux) et
en comblant les champs inexistants avec une valeur nulle.
Exemple :
Pour avoir les enregistrements du niveau 1 (1 champ)
SELECT c2 AS Nv1
FROM T
WHERE (c3 Is Null)

Pour avoir les enregistrements du niveau 2 (2 champs)
SELECT N1.c2, N2.c2
FROM T AS N2 INNER JOIN T AS N1 ON N2.c3=N1.c1
WHERE (N2.c3 Is Not Null) And (N1.c3 Is Null)

Pour avoir les enregistrements du niveau 3 (3 champs)
SELECT N1.c2, N2.c2, N3.c2
FROM T AS N3 INNER JOIN (T AS N2 INNER JOIN T AS N1
ON N2.c3=N1.c1) ON N3.c3=N2.c1
WHERE (N3.c3 Is Not Null) And (N2.c3 Is Not Null) And (N1.c3 Is Null);

et pareil jusqu'au 13ème niveaux

Ce qui donne pour la requête union pour 3 champs (niveaux)
SELECT c2 AS Nv1, Null AS Nv2, Null AS Nv3
FROM T
WHERE (c3 Is Null)
UNION SELECT N1.c2, N2.c2, Null
FROM T AS N2 INNER JOIN T AS N1 ON N2.c3=N1.c1
WHERE (N2.c3 Is Not Null) And (N1.c3 Is Null)
UNION SELECT N1.c2, N2.c2, N3.c2
FROM T AS N3 INNER JOIN (T AS N2 INNER JOIN T AS N1
ON N2.c3=N1.c1) ON N3.c3=N2.c1
WHERE (N3.c3 Is Not Null) And (N2.c3 Is Not Null) And (N1.c3 Is Null);


PS: J'ai reformulé la requête pour utiliser plus facilement le copier/coller.


"moromain" a écrit dans le message de news:
Je ne comprends pas tout. Je ne connais pas bien le langage SQL.
Les N1, N2, N3 correspondent à quoi ? A Nv1, Nv2, Nv3 ??
___
SELECT c2 AS Nv1, Null AS Nv2, Null AS Nv3
FROM T
WHERE (c3 Is Null)
UNION SELECT N1.c2, N2.c2, Null
___
Ici, on référence quoi ?
Si C3 est null, on parle alors du niveau hiérarchique le plus haut ?

______
FROM T AS N1 INNER JOIN T AS N2 ON N1.c1=N2.c3
on recherche les niveaux "père".




WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null)
Là je comprends pas !A quoi correspondent les Nx.Cy ???




UNION SELECT N1.c2, N2.c2, N3.c2
FROM T AS N1 INNER JOIN (T AS N2 INNER JOIN T AS N3
ON N2.c1=N3.c3) ON N1.c1=N2.c3
WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null) And (N3.c3 Is Not Null);



Avatar
Michel_D
Nv1, Nv2, Nv3 sont des alias arbitraire des noms de champs
N1, N2, N3 sont des alias arbitraire du nom de la table, alias auquel
il faut ensuite se référer lorsqu'on utilise un champ de la table.

Dans la requête suivante on ne garde que les enregistrements qui ont
une relation "fil-père" -> ON N2.c1=N3.c3) ON N1.c1=N2.c3
et on écarte les enregistrements qui ne respectent pas les conditions
WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null) And (N3.c3 Is Not Null)

SELECT N1.c2, N2.c2, N3.c2
FROM T AS N1 INNER JOIN (T AS N2 INNER JOIN T AS N3
ON N2.c1=N3.c3) ON N1.c1=N2.c3
WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null) And (N3.c3 Is Not Null);


"moromain" a écrit dans le message de news:
Je ne comprends pas tout. Je ne connais pas bien le langage SQL.
Les N1, N2, N3 correspondent à quoi ? A Nv1, Nv2, Nv3 ??
___
SELECT c2 AS Nv1, Null AS Nv2, Null AS Nv3
FROM T
WHERE (c3 Is Null)
UNION SELECT N1.c2, N2.c2, Null
___
Ici, on référence quoi ?
Si C3 est null, on parle alors du niveau hiérarchique le plus haut ?

______
FROM T AS N1 INNER JOIN T AS N2 ON N1.c1=N2.c3
on recherche les niveaux "père".




WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null)
Là je comprends pas !A quoi correspondent les Nx.Cy ???




UNION SELECT N1.c2, N2.c2, N3.c2
FROM T AS N1 INNER JOIN (T AS N2 INNER JOIN T AS N3
ON N2.c1=N3.c3) ON N1.c1=N2.c3
WHERE (N1.c3 Is Null) And (N2.c3 Is Not Null) And (N3.c3 Is Not Null);



Avatar
moromain
Je rentre de 3 jours d'absence.
MERCI BEAUCOUP Michel. Tu as fait un sacré boulot !!
J'ai à peu près compris le principe.
Le fichier s'ouvre bien (autant de code, ça fait peur !!).
Je vais l'intégrer dans ma base dans les prochains jours.
En tout cas, merci à tous pour votre disponibilité.

J'espère que ce post servira à d'autres !
1 2