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

Requêtes MySQL Discussion :

Sélectionner les sujets qui ont 0 messages


Sujet :

Requêtes MySQL

  1. #1
    Membre du Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Juillet 2006
    Messages
    78
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2006
    Messages : 78
    Points : 50
    Points
    50
    Par défaut Sélectionner les sujets qui ont 0 messages
    Bonjour à tous,

    Je migre un forum d'une plateforme à une autre (Connectix Boards vers PhpBB3) et je suis à la phase import des sujets.

    Cependant en développant mon script qui va piocher d'un côté pour insérer de l'autre, je me suis rendu compte que pas mal de sujets ont 0 messages, du coup je voudrais les supprimer dans la table `cb_topics` avant de faire tourner mon script.

    Y'a + de 50.000 sujets dans cette table mais seuls 47.000 d'entre eux ont des messages.

    Du coup je tente ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT topic_id from cb_topics WHERE topic_id NOT IN (SELECT msg_topicid AS topic_id FROM cb_messages GROUP BY msg_topicid HAVING COUNT( msg_id ) >0) LIMIT 0,10
    Mais mysql n'a pas aimé

    La sous-requête passe au poil par contre (c'est là que j'obtiens 47000 résultats par rapport aux 50000 topics existants).

    Donc d'un côté une table `cb_messages` qui comporte msg_id et msg_topicid (l'id du topic auquel le message appartient) et de l'autre une table `cb_topics`qui comporte topic_id

    Je veux trouver, puis éliminer les topics dont l'id n'est référencé dans aucun enregistrement de la table messages.

    Des conseils pour le faire proprement et en douceur, je vais me faire gronder si je continue à faire tomber mysql

    Merci

  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 803
    Points
    30 803
    Par défaut
    Tout simplement comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT  topic_id
    from    cb_topics   tpc
    WHERE   not exists
            (   SELECT  null
                FROM    cb_messages msg
                where   msg.msg_topicid = tpc.topic_id
            )
    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
    Membre du Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Juillet 2006
    Messages
    78
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2006
    Messages : 78
    Points : 50
    Points
    50
    Par défaut
    Merci mais je t'avoue que ça n'est pas limpide pour moi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT  topic_id
    from    cb_topics   tpc
    WHERE   not exists
            (   SELECT  null
                FROM    cb_messages msg
                where   msg.msg_topicid = tpc.topic_id
            )
    si je traduis en français, c'est : trouver les topic_id, n'existant pas dans la sous-requête, qui retourne "rien" à chaque fois qu'elle trouve une correspondance entre msg_topicid et topic_id (correspondance qui se produit à chaque fois qu'il se trouve un message dont le champ msg_topicid a la valeur de topic_id)

    point de vue charge de la base, c'est plutôt soft ou pas ? pas envie de refaire mal à mysql

    merci pour ton retour et désolé de ne pas avoir répondu plus tôt, j'étais sur la route tout l'après-midi

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 912
    Points
    38 912
    Billets dans le blog
    9
    Par défaut
    Une requête (NOT)EXISTS a pour résultat un booléen vrai/faux et ce quelque soit le contenu de la clause SELECT.

    par exemple WHERE EXISTS (SELECT 1 FROM MA_TABLE WHERE MA_COLONNE = 1) renvoie exactement la même chose que WHERE EXISTS (SELECT * FROM MA_TABLE WHERE MA_COLONNE = 1).

    On utilise souvent une constante (SELECT 1) voire une division par zéro (SELECT1/0) peu importe.
    Attention toutefois SELECT NULL n'est pas supporté par tous les SGBD

  5. #5
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 066
    Points
    19 066
    Par défaut
    Salut à tous.

    Bonne année, bonne santé, mes meilleurs voeux à toutes et à tous pour l'année 2020.

    Citation Envoyé par Lomic
    Mais mysql n'a pas aimé
    C'est normal car le "in" ne sait gérer qu'un nombre limité de valeurs.
    Vous avez le choix entre augmenter cette capacité ou utiliser le "exists" à la place.
    La bonne façon de faire est la solution proposée par al1_24.

    Mais en regardant de plus près, je constate que votre requête n'est pas conforme à ce que vous cherchez à faire.
    Il est totalement inutile d'utiliser LIMIT.
    Pourquoi passer par une sous requête et ne pas faire une jointure ? Voici ce que je vous propose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select           t1.topics_id,
                     count(msg_id) as nbre
               from  cb_topics as t1
     
    left outer join  cb_messages as t2
                 on  t2.msg_topicid = t1.topics_id
     
           group by  t1.topics_id
             having  nbre < 1
    Pour des raisons de performances, vérifiez :
    a) la colonne msg_topicid doit être une clef étrangère.
    b) mettre un index sur la colonne msg_id.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  6. #6
    Membre du Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Juillet 2006
    Messages
    78
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2006
    Messages : 78
    Points : 50
    Points
    50
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    C'est normal car le "in" ne sait gérer qu'un nombre limité de valeurs.
    bon à savoir


    Il est totalement inutile d'utiliser LIMIT.
    juste un exemple de mes compétences limitées en SQL je me suis dit que ça limiterait le nombre de résultats que la requête me sortirait, des fois que ça charge un peu trop le serveur, au moins il ne me sortirait que les 30 premiers résultats
    Pourquoi passer par une sous requête et ne pas faire une jointure ?
    parce que j'ai du mal avec les jointures


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select           t1.topics_id,
                     count(msg_id) as nbre
               from  cb_topics as t1
     
    left outer join  cb_messages as t2
                 on  t2.msg_topicid = t1.topics_id
     
           group by  t1.topics_id
             having  nbre < 1
    Je comprend ce code merci pour ces explications intéressantes et bonne année également

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 198
    Points : 12 774
    Points
    12 774
    Par défaut
    Bonjour,
    On peut simplifier la requête d'Artemus24:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    select t1.topics_id,
    from cb_topics as t1
    left outer join cb_messages as t2
    on  t2.msg_topicid = t1.topics_id
    where t2.msg_topicid is null

    Tatayo.

  8. #8
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 066
    Points
    19 066
    Par défaut
    Salut à tous.

    Citation Envoyé par Lomic
    parce que j'ai du mal avec les jointures
    A votre âge, avoir des problèmes de jointures ou de genoux (je - nous).
    C'est pas bon du tout pour le relationnel !

    Citation Envoyé par Tatayo
    On peut simplifier la requête d'Artemus24:
    Merci Tatayo, je n'avais pas pensé au NULL.

    C'est excellent, ça mérite '+1'.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  9. #9
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par tatayo Voir le message
    Bonjour,
    On peut simplifier la requête d'Artemus24:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    select t1.topics_id,
    from cb_topics as t1
    left outer join cb_messages as t2
    on  t2.msg_topicid = t1.topics_id
    where t2.msg_topicid is null

    Tatayo.
    C'est ce que l'on appelle une semi anti-jointure.
    • SEMI : parce que l'on ne veut que les informations d'une des tables de la jointure et pas de l'autre.
    • ANTI : parce que l'on filtre sur le fait que la jointure ne se fait pas entre les deux tables.


    D'où l'OUTER JOIN accompagné par le filtre WHERE …. IS NULL

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 31/01/2014, 11h38
  2. Sélectionner les parents qui n'ont pas d'enfants roux
    Par MatthieuBrunet dans le forum Requêtes
    Réponses: 4
    Dernier message: 12/05/2008, 13h17
  3. [XSL] Sélectionner les éléments qui n'ont pas un certain fils
    Par lebechen dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 05/07/2006, 17h54
  4. supprimer les fichiers qui ont des mêmes noms
    Par manaboko dans le forum Langage
    Réponses: 5
    Dernier message: 08/03/2006, 09h09
  5. Selectionner les date qui ont minimum une heure d'ecart
    Par uraxyd dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 26/07/2005, 13h39

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