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

SQL Firebird Discussion :

[FB 2.5] delete condition sur autre table


Sujet :

SQL Firebird

  1. #1
    jlf
    jlf est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 140
    Points : 49
    Points
    49
    Par défaut [FB 2.5] delete condition sur autre table
    bonjour

    soient 2 tables T1 et T2
    une colonne C dans T1 et T2
    C est clef primaire dans T1 (valeur unique) mais pas dans T2

    je voudrais supprimer les lignes de T1 pour lesquelles n lignes de T2 répondent à la condition T1.C = T2.C
    autrement dit je voudrais supprimer les lignes de T1 dont la valeur de C se trouve n fois dans T2, n pouvant être égal à zéro (pas d'occurence)

    je vois pas trop comment faire, merci de votre aide

  2. #2
    Expert éminent
    Avatar de qi130
    Homme Profil pro
    Expert Processus IT
    Inscrit en
    Mars 2003
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Expert Processus IT
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 3 905
    Points : 6 031
    Points
    6 031
    Par défaut
    J'ai un pb de compréhension avec ta demande: les 2 formulations ne me semblent pas équivalentes....

    Pour T1.C = T2.C
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    delete from T1
    where C in (select c from T2)
    Pour la 2nde formulation, la "précision"
    n pouvant être égal à zéro (pas d'occurence)
    conduit à tout supprimer
    "Il n'y a pas de bonnes réponses à une mauvaise question." (M. Godet)
    -----------------------
    Pensez à cloturer votre sujet - Aucune réponse aux sollicitations techniques par MP
    Usus magister est optimus

  3. #3
    Membre éclairé Avatar de freud
    Homme Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    1 271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 271
    Points : 681
    Points
    681
    Par défaut
    Bonjour,

    Vous pouvez utiliser ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    delete FROM T1 WHERE T1.C IN (SELECT T2.C FROM T2 WHERE T1.C=T2.C)
    Mais T2 gardera des lignes orphelins de T1..........
    Il faudrait que T2 puisse avoir une clé étrangère qui est la clé primaire de T1 le champ C et de poser une contrainte de suppression en cascade (ON DELETE CASCADE).
    Si quelqu'un t'a offensé, ne cherche pas à te venger; assieds-toi au bord de la rivière et, bientôt, tu verras passer son cadavre.

    Lao Tseu - un sage chinois

    Celui qui lutte contre les monstres doit veiller à ne pas le devenir lui-même.
    Et quand ton regard pénètre longtemps au fond d'un abîme, l'abîme, lui aussi, pénètre en toi.

    Friedrich Nietzsche - Par délà le bien et le mal

  4. #4
    Membre éclairé Avatar de freud
    Homme Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    1 271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 271
    Points : 681
    Points
    681
    Par défaut
    Excusez moi qi130 nos posts se sont croisés.

    Citation Envoyé par jlf
    n pouvant être égal à zéro (pas d'occurence)
    Effectivement c'est un problème de compréhension
    Et j'ai mis un WHERE en plus .
    Si quelqu'un t'a offensé, ne cherche pas à te venger; assieds-toi au bord de la rivière et, bientôt, tu verras passer son cadavre.

    Lao Tseu - un sage chinois

    Celui qui lutte contre les monstres doit veiller à ne pas le devenir lui-même.
    Et quand ton regard pénètre longtemps au fond d'un abîme, l'abîme, lui aussi, pénètre en toi.

    Friedrich Nietzsche - Par délà le bien et le mal

  5. #5
    jlf
    jlf est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 140
    Points : 49
    Points
    49
    Par défaut
    je me suis mal exprimé, un exemple sera peut-être plusd clair :

    dans T1 j'ai les lignes suivantes :
    A
    B
    C
    (pas de doublons possibles dans T1)

    et dans T2 :
    A
    A
    B


    je veux pouvoir supprimer dans T1 les lignes ayant n occurences dans T2, n arbitraire
    donc :
    si n= 0, je dois supprimer la ligne "C" de T1
    si n=2, je dois supprimer "A"

  6. #6
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Ce n'est pas "n" arbitraire mais "n" est un paramètre d'entrée de la requête.

    Je verais bien un truc du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    DELETE FROM T1
    WHERE T1.C IN (SELECT T2.c FROM T2 group by T2.C having count(T2.c)=:n);

  7. #7
    jlf
    jlf est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 140
    Points : 49
    Points
    49
    Par défaut
    Ce n'est pas "n" arbitraire mais "n" est un paramètre d'entrée de la requête
    oui c'est vrai, pardon pour cette imprécision

    une clause HAVING résoud effectivement le pbm, je n'y avais pas pensé car je connais mal cette clause, merci Barbibulle

    malheureusement j'ai en réalité besoin d'étendre mon DELETE à une scrutation sur plusieurs générations de tables filles
    j'avais simplifié ma question car je pensais pouvoir généraliser facilement mais pour le coup j'ai du mal à le faire

    par exemple si j'étends l'ex précédent à 3 tables T1 .. T3 ça donne :

    T1 une seule colonne C1 en primary key :
    A1
    B1
    C1

    T2, deux colonnes : C2 primary key et C1 foreign key sur T1 :
    A2, A1
    B2, A1
    C2, B1

    T3, deux colonnes : C3 primary key et C2 foreign key sur T2

    A3, A2
    B3, A2
    C3, B2
    D3, C2

    les 3 1ères lignes de T3 remontent à A1 de T1, et la quatrième ligne à B1
    donc :
    - si :n=0 le DELETE doit supprimer C1 de T1
    - si :n=3 le DELETE doit supprimer A1

    est-ce toujours possible avec un HAVING ?

  8. #8
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Oui, il suffit de faire une jointure entre T2 et T3 dans le sous select.

    Mais votre exemple ne permet pas de savoir exactement ce que vous souhaitez.

    Mais je serais tenté de dire que vous souhaitez trouver les enregistrements ayant "n" fils dans T3.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DELETE FROM T1
    WHERE T1.C1 IN (SELECT T2.c1 FROM T2 
      inner join T3 on (T3.C2=T2.C2) 
      GROUP BY T2.C1 
      HAVING count(T3.c3)=:n);

  9. #9
    jlf
    jlf est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 140
    Points : 49
    Points
    49
    Par défaut
    OK merci Barbibulle

    le HAVING sait donc qu'il doit faire son COUNT sur T3 en groupant sur le grand-père de T1, bien que le SELECT porte sur T2 et donc que l'ensemble remonté ne contient par l'INNER qu'une seule occurence de T3 par ligne de T2

    autrement dit j'aurais pensé qu'il donnerait :n=2 pour A1


    j'aurais jamais trouvé, c'est contre-intuitif ou c'est mon intuition qui pédale ?

    en tous cas merci encore

  10. #10
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Je ne comprend pas votre lecture de la requête.

    Pour moi il faut :

    Rechercher la liste des identifiants de T1 dont il faut supprimer les enregistrements. (Delete from T1 where T1.C1 in (Liste))

    La liste c'est l'ensemble des enregistrements de T2 ayant un fil dans T3 que je groupe par identifiant C1 pour compter les enregistrements.

    Et c'est en me relisant que je m'aperçois que la requête ne marche pas pour n=0.

    Et de toute façon avant de pouvoir écrire une requête correcte il faudrait que vous définissiez un peu mieux les différents cas.

    Par exemple peut il arriver d'avoir des éléments dans T2 n'ayant pas de fils dans T3. Ces éléments entre t'il en compte dans le comptage des fils ?

    Autrement dit si on ajoute à T2
    D2, C1
    E2, C1

    si n=2 doit dont supprimer C1 ? oubien quand n=0 ?

  11. #11
    jlf
    jlf est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 140
    Points : 49
    Points
    49
    Par défaut
    Je ne comprend pas votre lecture de la requête
    cas général : j'ai une cascade de "t" tables T1 .. Tt en relation 1-plusieurs

    chaque Ti contient 2 colonnes : une clef primaire et une clef étrangère sur Ti-1

    on établit une filiation entre l'ancêtre initial (ligne de T1) et les descendants ulitimes (lignes de Tt), sans se préoccuper du nombre de descendants intermédiaires dans chacune des T2 .. Tn-1

    le but est de pouvoir supprimer les ancêtres initiaux de T1 ayant n descendants dans Tt, n >= 0

    la requête sera rédigée pour un "t" donné (autant de requetes que de "t" possibles), et dans l'idéal devrait être paramètrable en fonction de "n"

    a priori la soluce pour t=3 sera extensible à un t quelconque et me suffit donc

    Et c'est en me relisant que je m'aperçois que la requête ne marche pas pour n=0
    au pire je peux faire 2 requêtes pour un "t" fixé, avec un "NOT IN" si n=0

    ça alourdit un peu le code PHP qui lance la demande mais pas excessivement, même si bien sûr le mieux serait de pouvoir paramètrer la même pour tous les "n"

  12. #12
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    J'ai comme l'impression que vous voulez gérer un "arbre".

    Dans ce cas pourquoi ne pas adopter une seule table pour gérer tout cela.
    Et plutot que de faire de l'auto jointure (ou de la récursivité dans des PS) regarder plutot cet article de Frédéric Brouard (alias SQLPro) :

    http://sqlpro.developpez.com/cours/arborescence/

    Lisez bien et notamment le paragraphe 2.14 qui améliore le modèle avec la notion de niveau (votre t du Tt).

  13. #13
    jlf
    jlf est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 140
    Points : 49
    Points
    49
    Par défaut
    merci pour cet article qui est vraiment très intéressant, je connaissais pas du tout et pense que j'aurai l'occasion de l'utiliser à l'avenir

    mais pas pour mon sujet actuel, revenir sur le modèle de données serait trop long et je crois mal adapté car les INSERT / DELETE sont quand même plus pénibles et moi j'en ai beaucoup
    par ailleurs les feuilles qui m'intéressent sont toujours au même niveau, ce qui constitue quand même une restriction substantielle du pbm général

    mais cet article ouvre indéniablement des horizons, de ces soluces élégantes dont j'ai la faiblesse d'être friand ;o)

    merci encore

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VBA-E] Minimum d'une colonne avec condition sur autre colonne
    Par Currahee dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 10/05/2007, 17h01
  2. [SQL] Problème condition sur 1 table
    Par Dwain dans le forum Langage SQL
    Réponses: 3
    Dernier message: 27/02/2007, 19h51
  3. Delete simultané sur plusieurs tables
    Par fk04 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 21/06/2006, 10h34
  4. DELETE imbriqués sur plusieurs tables ?
    Par Oberown dans le forum Langage SQL
    Réponses: 8
    Dernier message: 29/07/2005, 14h53
  5. update avec condition sur autre table
    Par allowen dans le forum Langage SQL
    Réponses: 5
    Dernier message: 01/04/2005, 15h02

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