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 :

Pagination avec table jointe et sous-requête


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Par défaut Pagination avec table jointe et sous-requête
    Bonjour,

    Comment faire une pagination propre à partir de 2 tables jointes (LEFT), avec une clause WHERE sur la table jointe ?

    Ce qui marche actuellement sans clause WHERE:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT o.*, ot.`tag`, ot.`value` as `tag_value`
    FROM (
    	SELECT o.* FROM `nx_order` AS o
    	ORDER BY o.`date_order`
    	LIMIT 20, 40
    ) AS o
    LEFT JOIN `nx_order_tag` AS ot
    	ON (ot.`order_id` = o.`id`)

    Mais si je veux ajouter un filtre sur la table ot, par ex:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	WHERE
    		(ot.tag <> 'E')
    je suis coincé: la clause WHERE mise simplement dans la sous-requête génère une erreur (la table ot n'est pas connue);
    et en ajoutant un autre LEFT JOIN dans la sous-requête, pour y faire rentrer la table ot, avec un GROUP BY sur la clé primaire de nx_order, la pagination devient erronée...

    Merci pour vos idées et conseils.

  2. #2
    Membre expérimenté
    Avatar de diablo-dz
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2014
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2014
    Messages : 75
    Par défaut
    Bonsoir
    t'as essayé avec avec cette requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT o.*, ot.`tag`, ot.`value` AS `tag_value`
    FROM (
    	SELECT o.* FROM `nx_order` AS o
    	ORDER BY o.`date_order`
    	LIMIT 20, 40
    ) AS o
    LEFT JOIN `nx_order_tag` AS ot
    	ON (ot.`order_id` = o.`id`) AND (ot.tag <> 'E')
    A+

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Par défaut
    Citation Envoyé par diablo-dz Voir le message
    Bonsoir
    t'as essayé avec avec cette requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT o.*, ot.`tag`, ot.`value` AS `tag_value`
    FROM (
    	SELECT o.* FROM `nx_order` AS o
    	ORDER BY o.`date_order`
    	LIMIT 20, 40
    ) AS o
    LEFT JOIN `nx_order_tag` AS ot
    	ON (ot.`order_id` = o.`id`) AND (ot.tag <> 'E')
    A+

    Ça semble le faire au niveau du filtrage, merci.

    En revanche un autre problème que je n'avais pas remarqué auparavant empêche de tester la pagination:

    cette requête retourne en effet systématiquement un nombre de résultats correspondant au nombre de lignes dans la table jointe ot, sans semble-t-il tenir compte du LIMIT de la sous-requête...

    Je ne l'avais pas vu parce qu'il se trouve que par hasard la table ot contient actuellement 40 lignes, ce qui correspondait à la valeur de LIMIT utilisée jusqu'ici.

    Si je change LIMIT à 20,30 ou 20,50 , j'obtiens toujours ... 40 résultats !

    Merci pour vos idées et éventuellement explications.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Par défaut
    Bon, je reformule pour tenter de mettre plus clairement en évidence la problématique.

    Table "t1": champs "id1" (clé primaire), "date"
    contient des enregistrements datés.

    Table "t2": champs "id2" (clé primaire), "id1", "tag", "value"
    contient des propriétés (tag) d'éléments de la table t1,
    avec chaque élément de t1 pouvant avoir de 0 à n propriétés.

    J'ai besoin de pouvoir extraire de manière paginée n éléments de t1, avec leurs propriétés (ou pas s'ils n'en ont pas), avec un filtre d'exclusion sur 1 ou plusieurs
    propriétés.

    Par ex, sortir les éléments 20 à 40 de t1 n'ayant pas QUE la propriété "E" (les éléments ayant plusieurs propriétés dont la "E" sont acceptés):

    La dernière requête tentée pour ce faire est la suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT t3.*, t2.`tag`, t2.`value` AS `tag_value`
    FROM (
      SELECT * FROM `t1`
      ORDER BY `date`
      LIMIT 20, 20
    ) AS t3
    LEFT JOIN `t2`
      ON (t2.`id1` = t1.`id1` AND t2.`tag` <> 'E')
    Mais au moins 2 problèmes ici:
    - elle sort un nombre de résultats égal au nombre total de lignes dans t2, et ne semble donc pas tenir compte du LIMIT de la sous-requête, ce même si t1 contient un grand nombre de lignes (?) ;
    - le filtrage "t2.tag <> 'E'" dans la clause ON de la requête principale va théoriquement fausser la pagination (si on parvient à faire fonctionner le LIMIT dans la sous-requête);

    Il faudrait logiquement mettre le filtre dans la sous-requête, pour que la table temporaire t3 contiennent les résultats de base filtrés, ordonnés et paginés; mais pour ce faire la table t2 doit y être connue, sans faire de JOIN pour préserver la pagination, et sans non plus à priori pouvoir faire de corrélation de table entre requête principale et sous requête (il me semble pas supportée pour les sous-requêtes FROM dans MySQL 5.5).

    Merci pour vos idées.

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Par défaut
    bonjour,


    je ne comprend pas a quoi sert votre sous-requete dans ce cas là.

    bref simplifiez, et le résultat devrait être bon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT t1.*, t2.`tag`, t2.`value` AS `tag_value`
    FROM `t1`
    LEFT JOIN `t2` ON (t2.`id1` = t1.`id1` AND t2.`tag` <> 'E')
    ORDER BY t1.date
    limit 20, 30

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Par défaut
    Citation Envoyé par punkoff Voir le message
    bonjour,


    je ne comprend pas a quoi sert votre sous-requete dans ce cas là.

    bref simplifiez, et le résultat devrait être bon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT t1.*, t2.`tag`, t2.`value` AS `tag_value`
    FROM `t1`
    LEFT JOIN `t2` ON (t2.`id1` = t1.`id1` AND t2.`tag` <> 'E')
    ORDER BY t1.date
    limit 20, 30
    Merci pour votre réponse.

    N'étant pas expert SGBD, mon raisonnement n'est peut-être effectivement pas le bon, mais si je suis votre suggestion, la pagination ne sera pas bonne puisqu'elle doit se faire uniquement sur la table principale t1 et non sur la jointure t1+t2 qui introduit potentiellement des lignes redondantes (éliminées en amont par un script PHP qui met les propriétés issues de t2 dans un tableau pour chaque ligne de t1), d'où l'intérêt supposé de la sous-requête qui est censée réaliser le filtrage et la pagination AVANT la jointure.

    J'ai aussi envisagé l'utilisation de GROUP_CONCAT pour parvenir à mes fins, mais ayant souvent lu que cette fonctionnalité était si possible à éviter, la sous-requête me semblait être, peut-être à tort, la plus appropriée.

Discussions similaires

  1. Critère de requete avec table jointe
    Par Boid' dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 03/05/2013, 09h33
  2. [Vxi3] Table dérivée et sous-requête
    Par 305yalou dans le forum Designer
    Réponses: 5
    Dernier message: 09/07/2010, 10h58
  3. GROUP BY avec TABLES JOINTES
    Par przvl dans le forum Requêtes
    Réponses: 1
    Dernier message: 07/04/2010, 11h52
  4. Suppression avec condition de type sous-requête
    Par matel dans le forum Langage SQL
    Réponses: 4
    Dernier message: 24/09/2008, 08h24
  5. évaluation du nom de la table via une sous requête
    Par _ceone dans le forum SQL Procédural
    Réponses: 0
    Dernier message: 22/10/2007, 15h47

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