IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Gestion des répertoires en SQL


Sujet :

Langage SQL

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut Gestion des répertoires en SQL
    Bonjour
    J'ai 2 tables:
    * files (nomfic, taille, id_repertoire)
    * folders (id, path, niveau) où niveau m'indiquent si il est de niveau 1, 2, 3 ... 12 etc..

    Comment calculer la somme des fichiers (et le poids total) de tous les répertoires de niveau 3 (et évidemment leurs sous-repertoires)?

    Le résultat doit etre:
    Nom du répertoire Niveau 3 (et de ses sous-répertoires), count(nomfic), SUM(taille)

    Je butte sur le "et de ses sous-répertoires" !!!

    Merci pour votre aide!!

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 789
    Points
    30 789
    Par défaut
    Quel est ton SGBD ? sa version ? Prend-il en charge les requêtes récursives ?
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    autant pour moi je n'ai pas été précis en effet:

    c'est sous phpMyAdmin 2.6.3 /MySQL 5.0.41

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Ce problème entre typiquement dans le cadre de la modélisation arborescente par représentation intervallaire développée par SQLPro dans son article.
    Si tu peux modifier ton modèle bien sûr...

    Sinon je crois que dans l'explication des avantage de son modèle il donne des exemples de requête selon ton modèle.

    A la réflexion je vois quand même un petit souci dans ton modèle : il n'y apparaît pas la filiation entre les répertoires !

    folders (id, path, niveau)
    1 '/home' 1
    2 '/home/user1' 2
    3 '/home/user2' 2
    4 '/home/user1/documents' 3

    Comment savoir si le folder 4 appartient à user1 ou à user2 sans aller chercher le morceau de path ?

    Je réitère mon conseil de te pencher sur la représentation intervallaire !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Houla..

    En effet folders est fait comme ça
    folders (id, path, niveau)
    1 '/home' 1
    2 '/home/user1' 2
    3 '/home/user2' 2
    4 '/home/user1/documents' 3

    et files(nomfic, taille, id_repertoire):
    fichier1,500,2
    fichier2,65400,1
    fichier3,460,3
    fichier3,400,1
    etc..

    Par le truchement d'une requete imbriquée, ça ne marchait pas??

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Encore une fois, on ne sait pas à quel répertoire de niveau 2 se rapporte le répertoire de niveau 3.

    Une façon simple d'enregistrer la filiation est d'ajouter dans la table folders une colonne donnant l'identifiant du répertoire parent :
    folders (id, path, niveau, id_parent)
    1 '/home' 1 0
    2 '/home/user1' 2 1
    3 '/home/user2' 2 1
    4 '/home/user1/documents' 3 2
    5 '/home/user2/documents' 3 3
    6 '/home/user1/documents/cv.doc' 4 4
    7 '/home/user1/documents/candidature.doc' 4 4

    Mais le problème avec cette structure, comme c'est expliqué, si mes souvenirs sont exacts, dans l'article de SQLPro, c'est qu'on ne connait pas à l'avance le nombre de niveaux, ce qui complique les requêtes, surtout si le SGBD ne prend pas en charge les requêtes récursives.

    Je n'ai jamais eu à la mettre en oeuvre mais je trouve la représentation intervallaire très intéressante.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Cette requête me donne l'information que je veux mais j'inscrits ici manuellement le répertoire de niveau 3 (P:/NIV1/NIV2/NIV3)
    Comment mettre ce répertoire de niveau 3 en variable?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT folders.path, count( files.filename ) AS NBFICHIERS, sum( taille ) AS TOTAL_Mo
    FROM files INNER JOIN folders ON files.folder_id = folders.id
    WHERE folders.niveau>=3 AND folders.path LIKE 'P:/NIV1/NIV2/NIV3%'
    group by folders.path
    J'ai bien essayé un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT folders.path, count( files.filename ) AS NBFICHIERS, sum( taille ) AS TOTAL_Mo
    FROM files INNER JOIN folders ON files.folder_id = folders.id
    WHERE folders.path LIKE (
     
    SELECT folders.path
    FROM folders
    WHERE folders.niveau=3
    )
     
    GROUP BY folders.path
    Mais ça me dit que la SubQuery retourne plusieurs résultats...
    Je m'en sort pas!!....

  8. #8
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Il faut que tu modifies ta structure !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 152
    Points : 7 402
    Points
    7 402
    Billets dans le blog
    1
    Par défaut
    Je ne suis pas certain qu'il faille modifier la structure...

    Voici un exemple en vitesse sous SQL Server 2008 Express.
    Aucune fonction avancée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    drop table files
    go
     
    drop table folders
    go
     
    create table folders (id int primary key, path varchar(255), niveau int)
    go
    create table files (nomfic varchar(255), taille int, id_repertoire int references folders(id))
    go
     
    create unique index uix_files on files (id_repertoire, nomfic)
    go
     
    insert into folders values (1, 'c:\', 1);
    insert into folders values (2, 'c:\in', 2);
    insert into folders values (3, 'c:\in\test', 3);
    insert into folders values (4, 'c:\in\plop', 3);
    insert into folders values (5, 'c:\windows', 2);
    insert into folders values (6, 'c:\windows\system', 3);
    insert into folders values (7, 'c:\windows\temp', 3);
     
    insert into files values ('swap.swp', 268435456, 1);
    insert into files values ('autoexec.bat', 589, 1);
    insert into files values ('backup.bck', 56485657, 2);
    insert into files values ('mail.pst', 654566, 3);
    insert into files values ('archive.pst', 54684, 3);
    insert into files values ('cv.doc', 5859, 4);
    insert into files values ('comptes.xls', 89632, 4);
    insert into files values ('win.com', 5645648, 5);
    insert into files values ('notepad.exe', 5854549, 5);
    insert into files values ('dviers.drv', 58549, 6);
    insert into files values ('cv.doc', 5485, 7);
    insert into files values ('comptes.xls', 55549, 7);
     
    select f1.id, f1.path, f1.niveau, SUM(f3.taille) tailles
    from folders f1
    inner join folders f2 on f2.niveau >= f1.niveau and f2.path like f1.path + '%'
    inner join files f3 on f3.id_repertoire = f2.id
    group by f1.id, f1.path, f1.niveau;
    On ne jouit bien que de ce qu’on partage.

  10. #10
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 152
    Points : 7 402
    Points
    7 402
    Billets dans le blog
    1
    Par défaut
    Et répondre à la question initiale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select f1.id, f1.path, f1.niveau, SUM(f3.taille) tailles
    from folders f1
    inner join folders f2 on f2.niveau >= f1.niveau and f2.path like f1.path + '%'
    inner join files f3 on f3.id_repertoire = f2.id
    where f1.niveau = 3
    group by f1.id, f1.path, f1.niveau
    On ne jouit bien que de ce qu’on partage.

  11. #11
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Beau travail de la part de la part de StringBuilder : je vote cinq étoiles.

    Une simple remarque : afin de faire apparaître les répertoires qui sont au niveau feuille et sont vides (idem pour leurs ascendants tout aussi vides) on pourrait remplacer le 2e INNER JOIN par un LEFT JOIN :
    LEFT JOIN files f3 ON f3.id_repertoire = f2.id
    Et par voie de conséquence — à cause du bonhomme NULL qui ne manquera pas de se manifester — remplacer SUM(f3.taille) par COALESCE(SUM(f3.taille), 0).
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  12. #12
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Et répondre à la question initiale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select f1.id, f1.path, f1.niveau, SUM(f3.taille) tailles
    from folders f1
    inner join folders f2 on f2.niveau >= f1.niveau and f2.path like f1.path + '%'
    inner join files f3 on f3.id_repertoire = f2.id
    where f1.niveau = 3
    group by f1.id, f1.path, f1.niveau
    L'idée est peut-être intéressante mais la requête ne fonctionnera pas pour au moins deux raisons.
    D'abord une raison conceptuelle: si au niveau 3, il y a deux répertoires c:\a\b\rep1 et c:\a\b\rep10, la requête va inclure les fichiers de rep10 dans la somme pour rep1, donc le résultat final sera faux.

    Il y a aussi une raison technique: dans l'argument de droite de LIKE, les caractères %, _ sont traités spécialement alors qu'ils sont valides dans un chemin sur disque. De plus le caractère \ est aussi traité spécialement pour certains SGBD et notamment mysql (normalement il faut utiliser la clause ESCAPE pour supprimer ce comportement, mais voir la doc de LIKE spécifique au SGBD)
    Dernière remarque: ne pas utiliser l'opérateur + pour la concaténation de chaine, avec mysql ça donnera un résultat numérique, en général 0.

  13. #13
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par estofilo Voir le message
    La requête ne fonctionnera pas [...]
    D'abord une raison conceptuelle: si au niveau 3, il y a deux répertoires c:\a\b\rep1 et c:\a\b\rep10, la requête va inclure les fichiers de rep10 dans la somme pour rep1, donc le résultat final sera faux.
    Examinons le résultat de la requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    id   path               niveau    tailles
     1   c:\                     1  337346223
     2   c:\IN                   2   57290398
     3   c:\IN\test              3     709250
     4   c:\IN\plop              3      95491
     5   c:\windows              2   11619780
     6   c:\windows\system       3      58549
     7   c:\windows\temp         3      61034
    Le grand philosophe Ludwig Wittgenstein a écrit :
    Toutes les différences logiques sont de grandes différences.
    Hugh Darwen et Chris Date fournissent à leur tour le corollaire suivant :
    Toutes les erreurs logiques sont de grandes erreurs.
    Si l’on vous suit, il y aurait une erreur logique : la requête « inclurait » la somme des fichiers de c:\windows\temp dans la somme des fichiers de c:\windows\system, en vertu de quoi, pour ce répertoire, la valeur de l’attribut tailles devrait être égale à 119583 au lieu de 58549. Il y aurait donc là une grande différence, une grave erreur, mais manifestement le résultat ne confirme pas votre propos. Sous réserve d'une démonstration de ce que vous avancez, la requête est réputée correcte.


    Citation Envoyé par estofilo Voir le message
    Il y a aussi une raison technique [...]
    StringBuilder a bien précisé que la requête fonctionnait avec SQL Server 2008 Express. Elle fonctionne aussi avec SQL Server 2005 (et je pense avec DB2, à condition de remplacer l'opérateur de concaténation « + » par « || »). Concernant MySQL, à vous de procéder aux aménagements qui vous conviennent, mais on est au niveau du détail, c’est une affaire de petite différence...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  14. #14
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    la requête « inclurait » la somme des fichiers de c:\windows\temp dans la somme des fichiers de c:\windows\system
    Non, je ne me suis pas fait comprendre, visiblement, alors détaillons le problème. Mon exemple est c:\a\b\rep1 et c:\a\b\rep10 et il a une particularité que n'ont pas c:\windows\temp et c:\windows\system, c'est que le 1er chemin est une sous-chaine ancrée à gauche du second chemin.
    Dit en SQL, ça implique que f2.path LIKE f1.path || '%' va être VRAI alors même que f1.path n'est pas du tout un parent de f2.path. Là est le problème.

    Avec le jeu d'essai fourni plus haut, il faudrait par exemple renommer c:\IN\plop en c:\IN\testplop
    Et dans ce cas, la taille annoncée par la requête pour le répertoire c:\IN\test serait fausse.

  15. #15
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir,


    Citation Envoyé par estofilo Voir le message
    Non, je ne me suis pas fait comprendre, visiblement, alors détaillons le problème. Mon exemple est c:\a\b\rep1 et c:\a\b\rep10 et il a une particularité que n'ont pas c:\windows\temp et c:\windows\system, c'est que le 1er chemin est une sous-chaine ancrée à gauche du second chemin.
    Dit en SQL, ça implique que f2.path LIKE f1.path || '%' va être VRAI alors même que f1.path n'est pas du tout un parent de f2.path. Là est le problème.
    Vous avez raison, bravo. Wittgenstein me tirerait les oreilles... J’espère que StringBuilder a un correctif. Quoi qu’il en soit, il mérite bien ses étoiles.

    Ceci dit, on pourrait suivre l’avis de CinePhil, c'est-à-dire changer la structure :



    D’où les tables :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    CREATE TABLE FOLDERS 
    (      
           FolderId       INT           NOT NULL
         , Path           VARCHAR(255)  NOT NULL
      , CONSTRAINT FOLDERS_PK PRIMARY KEY (FolderId)
    ) ;
    CREATE TABLE HIERARCHIE
    (
           FolderId       INT           NOT NULL
         , FolderParent   INT           NOT NULL
     , CONSTRAINT HIERARCHIE_PK PRIMARY KEY (FolderId) 
     , CONSTRAINT HIERARCHIE_FK1 FOREIGN KEY (FolderId) REFERENCES FOLDERS
     , CONSTRAINT HIERARCHIE_FK2 FOREIGN KEY (FolderParent) REFERENCES FOLDERS
    ) ;
     
    CREATE TABLE FILES 
    (
          FichierId     INT                NOT NULL
        , FichierNom    VARCHAR(255)       NOT NULL
        , Taille        INT                NOT NULL
        , RepertoireId  INT                NOT NULL 
      , CONSTRAINT FILES_PK PRIMARY KEY (FichierId) 
      , CONSTRAINT FILES_FOLDERS_FK FOREIGN KEY (id_repertoire) REFERENCES FOLDERS
    ) ;

    Les INSERT :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    INSERT INTO FOLDERS VALUES (0001,  'C:\');
    INSERT INTO FOLDERS VALUES (0011,  'C:\11');
    INSERT INTO FOLDERS VALUES (0111,  'C:\11\111');
    INSERT INTO FOLDERS VALUES (1111,  'C:\11\111\1111');  -- A surveiller !
    INSERT INTO FOLDERS VALUES (11110, 'C:\11\111\11110'); -- A surveiller !
    INSERT INTO FOLDERS VALUES (11111, 'C:\11\111\1111\11111');
    INSERT INTO FOLDERS VALUES (0112,  'C:\11\112');
    INSERT INTO FOLDERS VALUES (0113,  'C:\11\113');
    INSERT INTO FOLDERS VALUES (0012,  'C:\12');
    INSERT INTO FOLDERS VALUES (0121,  'C:\12\121');
    INSERT INTO FOLDERS VALUES (0122,  'C:\12\122');
    INSERT INTO FOLDERS VALUES (0013,  'C:\13');
    INSERT INTO FOLDERS VALUES (0131,  'C:\13\131');
    INSERT INTO FOLDERS VALUES (0132,  'C:\13\132'); 
    INSERT INTO FOLDERS VALUES (1321,  'C:\13\132\1321'); 
    INSERT INTO FOLDERS VALUES (1322,  'C:\13\132\1322'); 
    INSERT INTO FOLDERS VALUES (0133,  'C:\13\133'); 
    INSERT INTO FOLDERS VALUES (1331,  'C:\13\133\1331'); 
    
    INSERT INTO HIERARCHIE VALUES (0011,  0001);
    INSERT INTO HIERARCHIE VALUES (0111,  0011);
    INSERT INTO HIERARCHIE VALUES (1111,  0111);     -- A surveiller !
    INSERT INTO HIERARCHIE VALUES (11110, 0111);     -- A surveiller !
    INSERT INTO HIERARCHIE VALUES (11111, 1111);
    INSERT INTO HIERARCHIE VALUES (0112,  0011);
    INSERT INTO HIERARCHIE VALUES (0113,  0011);
    INSERT INTO HIERARCHIE VALUES (0012,  0001);
    INSERT INTO HIERARCHIE VALUES (0121,  0012);
    INSERT INTO HIERARCHIE VALUES (0122,  0012);
    INSERT INTO HIERARCHIE VALUES (0013,  0001);
    INSERT INTO HIERARCHIE VALUES (0131,  0013);
    INSERT INTO HIERARCHIE VALUES (0132,  0013); 
    INSERT INTO HIERARCHIE VALUES (1321,  0132); 
    INSERT INTO HIERARCHIE VALUES (1322,  0132); 
    INSERT INTO HIERARCHIE VALUES (0133,  0013); 
    INSERT INTO HIERARCHIE VALUES (1331,  0133);
    
    INSERT INTO FILES VALUES (01, '1.swp',     0003,   0001);
    INSERT INTO FILES VALUES (02, '1.bat',     0002,   0001);
    INSERT INTO FILES VALUES (03, '1.bak',     0000,   0001);
    INSERT INTO FILES VALUES (04, '11.doc',    0017,   0011);
    INSERT INTO FILES VALUES (05, '111.xls',   0100,   0111);
    INSERT INTO FILES VALUES (06, '111.ppt',   0000,   0111);
    INSERT INTO FILES VALUES (07, '111.txt',   0107,    111);
    INSERT INTO FILES VALUES (08, '1111.doc',  0600,   1111);
    INSERT INTO FILES VALUES (09, '1111.wma',  2000,   1111);
    INSERT INTO FILES VALUES (10, '11111.doc', 0400,  11111);
    INSERT INTO FILES VALUES (11, '1112.wav',  0200,   11110);  -- A surveiller !
    INSERT INTO FILES VALUES (12, '1112.xls',  2801,   11110);  -- A surveiller !
    INSERT INTO FILES VALUES (13, '112.mp3',   0099,   0112);
    INSERT INTO FILES VALUES (14, '112.bak',   0014,   0112);
    INSERT INTO FILES VALUES (15, '12.bck',    0019,   0012);
    INSERT INTO FILES VALUES (16, '122.mid',   0000,   0122);
    INSERT INTO FILES VALUES (17, '131.mp3',   0000,   0131);
    INSERT INTO FILES VALUES (18, '1321.nwc',  5000,   1321);
    INSERT INTO FILES VALUES (19, '1322.nwc',  0500,   1322);



    Utilisation d’une jointure récursive, combinée avec la requête de StringBuilder :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    WITH V (FolderId, FolderParent, FolderPath, Niveau) AS 
     (
        SELECT FolderId, 0, CAST (FolderId AS VARCHAR(512)), 1
        FROM   FOLDERS AS x 
        WHERE  NOT EXISTS
               (SELECT ''
                FROM   HIERARCHIE AS y
                WHERE  x.FolderId = y.FolderId)     
      UNION ALL
        SELECT   x.FolderId, x.FolderParent
                 , CAST (v.FolderPath 
                   + cast(x.folderId AS VARCHAR(8))
                   + ',' + CAST (x.FolderId AS VARCHAR(512))AS VARCHAR(512))
               , v.Niveau + 1
        FROM   HIERARCHIE AS x JOIN V ON x.FolderParent = v.FolderId   
     )
    SELECT   x.FolderId
           , t.Path
           , x.niveau
           , COALESCE(SUM(z.taille), 0) AS taille
    FROM   V AS x
                   JOIN V AS y       ON  y.FolderPath LIKE x.FolderPath + '%' 
                                     AND y.niveau >= x.niveau 
                   LEFT JOIN FILES AS z 
                                     ON  z.RepertoireId = y.FolderId
                   JOIN FOLDERS AS t ON  x.FolderId = t.FolderId        
    GROUP BY x.FolderId, t.Path, x.FolderPath, x.niveau
    ORDER BY x.FolderPath

    Au résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    FolderId  Path                niveau   taille
    1         C:\                      1    11862
    11        C:\11                    2     6338
    111       C:\11\111                3     6208
    1111      C:\11\111\1111           4     3000
    11111     C:\11\111\1111\11111     5      400
    11110     C:\11\111\11110          4     3001
    112       C:\11\112                3      113
    113       C:\11\113                3        0
    12        C:\12                    2       19
    121       C:\12\121                3        0
    122       C:\12\122                3        0
    13        C:\13                    2     5500
    131       C:\13\131                3        0
    132       C:\13\132                3     5500
    1321      C:\13\132\1321           4     5000
    1322      C:\13\132\1322           4      500
    133       C:\13\133                3        0
    1331      C:\13\133\1331           4        0

    La requête est un peu tordue et certainement simplifiable, mais on devrait s'approcher de quelque chose de correct. Si vous avez des propositions, elles seront les bienvenues.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  16. #16
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir,


    La requête que j’ai fournie dans mon message précédent mérite d’être aménagée. En effet, le fait que le chemin soit fourni avec l’attribut Path de la table FOLDER fait qu’il y a une redondance, puisque l’on sait par ailleurs construire chaque chemin grâce à la table HIERARCHIE si l’on dispose du nom de chaque nœud (table FOLDER, attribut FolderNom). Par ailleurs, le SELECT final est celui de StringBuilder (à cette différence près que l’on accède à la table temporaire V et non pas à la table FOLDER).

    En conséquence, je redéfinis ainsi la table FOLDER :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TABLE FOLDERS 
    (      
           FolderId       INT             NOT NULL
         , FolderNom      VARCHAR(255)    NOT NULL
      , CONSTRAINT FOLDERS_PK PRIMARY KEY (FolderId)
    ) ;
    INSERT correspondants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    INSERT INTO FOLDERS VALUES (0001,  'C:');
    INSERT INTO FOLDERS VALUES (0011,  'Rep11');
    INSERT INTO FOLDERS VALUES (0111,  'Rep111');
    INSERT INTO FOLDERS VALUES (1111,  'Rep1111');  -- A surveiller !
    INSERT INTO FOLDERS VALUES (11110, 'Rep11110'); -- A surveiller !
    INSERT INTO FOLDERS VALUES (11111, 'Rep11111');
    INSERT INTO FOLDERS VALUES (0112,  'Rep112');
    INSERT INTO FOLDERS VALUES (0113,  'Rep113');
    INSERT INTO FOLDERS VALUES (0012,  'Rep12');
    INSERT INTO FOLDERS VALUES (0121,  'Rep121');
    INSERT INTO FOLDERS VALUES (0122,  'Rep122');
    INSERT INTO FOLDERS VALUES (0013,  'Rep13');
    INSERT INTO FOLDERS VALUES (0131,  'Rep131');
    INSERT INTO FOLDERS VALUES (0132,  'Rep132'); 
    INSERT INTO FOLDERS VALUES (1321,  'Rep1321'); 
    INSERT INTO FOLDERS VALUES (1322,  'Rep1322'); 
    INSERT INTO FOLDERS VALUES (0133,  'Rep133'); 
    INSERT INTO FOLDERS VALUES (1331,  'Rep1331');

    Aménagement de la requête :

    L’idée est de construire en plus du chemin en clair (Chemin), un 2e chemin qui lui soit équivalent (CheminDeTravail), mais tel qu’on suffixe le nom du répertoire en cours par un caractère qui ne peut pas figurer dans un nom de répertoire (« \ » par exemple sous WINDOWS) : ceci permet d’éviter l’absorption.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    WITH V (FolderId, FolderParent, Chemin, CheminDeTravail, Niveau) AS 
     (
        SELECT FolderId, 0,  CAST(FolderNom AS VARCHAR(512)), CAST(FolderId AS VARCHAR(512)), 1
        FROM   FOLDERS AS x 
        WHERE  NOT EXISTS
               (SELECT ''
                FROM   HIERARCHIE AS y
                WHERE  x.FolderId = y.FolderId)     
      UNION ALL
        SELECT   x.FolderId, x.FolderParent
               , CAST(v.Chemin + '\' + CAST(z.FolderNom AS VARCHAR(512)) AS VARCHAR(512))
               , CAST(v.CheminDeTravail
                 + '\'
                 + CAST(x.folderId AS VARCHAR(8))  -- Généralement plus court que FolderNom
                 + '\'                             -- Pour éviter l’absorption 
                 AS VARCHAR(512))
              , v.Niveau + 1
        FROM    HIERARCHIE AS x JOIN V ON x.FolderParent = v.FolderId 
                                JOIN FOLDERS AS z ON  x.FolderId = z.FolderId 
     )
    SELECT x.Chemin, x.Niveau, COALESCE(SUM(z.taille), 0) AS Taille        
    FROM   V AS x
                   JOIN V AS y       ON  y.CheminDeTravail LIKE x.CheminDeTravail + '%' 
                                     AND y.Niveau >= x.Niveau 
                   LEFT JOIN FILES AS z 
                                     ON  z.RepertoireId = y.FolderId
    GROUP BY x.Chemin, x.Niveau
    ORDER BY x.Chemin ;
    Au résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Chemin                           Niveau   Taille
    C:                                    1    11862
    C:\Rep11                              2     6338
    C:\Rep11\Rep111                       3     6208
    C:\Rep11\Rep111\Rep1111               4     3000
    C:\Rep11\Rep111\Rep1111\Rep11111      5      400
    C:\Rep11\Rep111\Rep11110              4     3001
    C:\Rep11\Rep112                       3      113
    C:\Rep11\Rep113                       3        0
    C:\Rep12                              2       19
    C:\Rep12\Rep121                       3        0
    C:\Rep12\Rep122                       3        0
    C:\Rep13                              2     5500
    C:\Rep13\Rep131                       3        0
    C:\Rep13\Rep132                       3     5500
    C:\Rep13\Rep132\Rep1321               4     5000
    C:\Rep13\Rep132\Rep1322               4      500
    C:\Rep13\Rep133                       3        0
    C:\Rep13\Rep133\Rep1331               4        0

    N.B. On est toujours dans un contexte SQL Server.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

Discussions similaires

  1. [WD10] gestion des répertoires
    Par misa dans le forum WinDev
    Réponses: 5
    Dernier message: 08/02/2010, 17h51
  2. gestion des répertoirs en c!
    Par ashley dans le forum C
    Réponses: 3
    Dernier message: 10/08/2009, 12h16
  3. [c# 2.0] Gestion des langues avec SQL
    Par oolon dans le forum Général Dotnet
    Réponses: 4
    Dernier message: 14/03/2007, 16h42
  4. gestion des utilisateurs, PL/SQL
    Par gama2ee dans le forum PL/SQL
    Réponses: 1
    Dernier message: 26/01/2007, 13h26
  5. [MS-DOS] Gestion des répertoires
    Par raph707 dans le forum Scripts/Batch
    Réponses: 3
    Dernier message: 19/09/2006, 18h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo