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

Développement SQL Server Discussion :

[..] LEFT JOIN TOP 1 [..]


Sujet :

Développement SQL Server

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 190
    Points : 59
    Points
    59
    Par défaut [..] LEFT JOIN TOP 1 [..]
    Bonjour,

    J'aimerai savoir s'il est possible (si oui, quelle est la synthaxe correcte) d'effectuer un TOP 1 après une jointure.

    Pour l'instant, j'ai la reqûete suivante (volontairement simplifié pour faciliter la compréhension de mon besoin) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM TABLE1 as a
    LEFT JOIN TABLE2 as B ON b.DATE BETWEEN a.DATE-365 and a.DATE-1
    J'aimerai maintenant que la requête s'arrête à la première jointure trouvée (par soucis de gain de temps)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM TABLE1 as a
    LEFT JOIN TOP 1 TABLE2 as B ON b.DATE BETWEEN a.DATE-365 and a.DATE-1

    Pourriez-vous m'aider ?

    Merci d'avance.

  2. #2
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    Vraiment bizarre cette demande...

    Vous voulez vous arretez a la 1ere jointure effectuée, mais vous faites une jointure externe (et ce, sans aucun tri ou clause particuliere)... C'est a dire que vous laissez la possibilité a la requete de vous ramener des tuples de la table2 NULL n'ayant pas de correspondance avec Table1, dans ce cas, autant ne pas faire de jointure et prendre la premiere ligne de votre Table1 !!

    Ex :

    Table1
    id - Date
    1 20110820
    2 20110821
    3 20110822

    Table2
    id - Date
    4 20110821
    5 20110822
    6 20110823

    Votre requete pourra vous rammener
    1 - 20110820 - NULL - NULL
    2 - 20110821 - 4 - 20110821
    3 - 20110822 - 5 - 20110822

    Et vous voulez vous arreter a votre 1ere jointure, soit
    1 - 20110820 - NULL - NULL

    Ce qui me parait tres etrange !!

    Peut etre ai je mal compris
    Dans la connaissance du monde, ceux qui ne savent rien en savent toujours autant que ceux qui n'en savent pas plus qu'eux. (Pierre Dac)

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 190
    Points : 59
    Points
    59
    Par défaut
    En reprenant votre exemple, voici dont j'ai besoin

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT *
    FROM TABLE1 AS a
    LEFT JOIN TOP 1 TABLE2 AS B
    ON b.DATE BETWEEN a.DATE-365 AND a.DATE-1
    AND NAME = 'M'
    (n'oubliez pas que j'ai simplifié mon code..)

    Table1
    id - Date
    1 20110820

    Table2
    id - Date - name
    2 20110812 M
    3 20110813 M
    4 20110814 F
    5 20110815 M
    6 20110816 F
    7 20110817 M
    8 20110818 M
    9 20110819 F
    10 20110820 M
    ...

    Ma requête peut me donner
    1 - 20110820 - 20110812 - M
    1 - 20110820 - 20110813 - M
    1 - 20110820 - 20110815 - M
    1 - 20110820 - 20110817 - M
    1 - 20110820 - 20110818 - M

    Et je veux m'arrêter à une seule jointure. Par exemple
    1 - 20110820 - 20110817 - M

  4. #4
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    et si a la place de

    Table1
    id - Date
    1 20110820


    Vous aviez

    Table1
    id - Date
    1 19110820

    Que devrait vous retourner votre requete ?
    Dans la connaissance du monde, ceux qui ne savent rien en savent toujours autant que ceux qui n'en savent pas plus qu'eux. (Pierre Dac)

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 190
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par Yanika_bzh Voir le message
    et si a la place de

    Table1
    id - Date
    1 20110820


    Vous aviez

    Table1
    id - Date
    1 19110820

    Que devrait vous retourner votre requete ?
    Ma requête me donnerait
    1 19110820 - NULL- NULL

    ce que je souhaite !

    Dans la majorité des cas, j'aurai, pour chacune des dates antérieures, une jointure possible. Mais parceque vérifier TOUTES les dates antérieures prend énormement de temps, j'aimerai m'arreter rapidement à la première jointure vérifié (et sinon, dans le cas contraire, la seule et unique (NULL-NULL)).

    J'insiste donc bien sur ma requête initiale : TOP 1 après un LEFT JOIN

    Merci de m'aider..

  6. #6
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    N'etant pas convaincu de l'utilité de votre demande pour le résultat souhaité, et du fait que vous ne maitrisiez pas parfaitement votre regle fonctionnelle, je ne vais pas m'aventurer a vous donner une solution.

    Peut etre que quelqu'un d'autre vous aidra sur ce forum.

    Bonne chance et bon courage
    Dans la connaissance du monde, ceux qui ne savent rien en savent toujours autant que ceux qui n'en savent pas plus qu'eux. (Pierre Dac)

  7. #7
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Personnellement je ne vois pas non plus la finalité ... pourriez vous nous expliquer clairement votre démarche ? Que souhaitez vous faire concrétement ?

    Sinon une solution possible mais non parfaite(sans avoir de critère de classement ou autre votre résultat ne sera pas vraiment déterministe ici ... c'est un peu la roulette russe)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT *
    FROM Table1 AS T1
    LEFT JOIN (SELECT TOP 1 * 
               FROM Table2) AS T2
     ON T2.[Date] BETWEEN T1.DATE-365 AND T1.DATE-1
    ++

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 190
    Points : 59
    Points
    59
    Par défaut
    Voici en détail :

    TABLE1
    ----------------------------------------------------
    DATE - ACCOUNT
    ----------------------------------------------------
    20110801 - AA


    TABLE2
    ----------------------------------------------------
    DATE2 - ACCOUNT - NAME
    ----------------------------------------------------
    20110801 - AA - X
    20110731 - AA - X
    20110730 - AA - X
    20110729 - AA - X
    20110728 - AA - M
    20110727 - AA - M
    20110726 - AA - M
    20110725 - AA - M
    20110724 - AA - M
    20110723 - AA - M
    20110722 - AA - M
    ...


    RESULTAT SOUHAITE
    ----------------------------------------------------
    DATE - ACCOUNT - TEST
    ----------------------------------------------------
    20110801 - AA - 1


    Voici mon code actuel:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT	DATE, 
    	ACCOUNT,
    	MAX(CASE WHEN NAME = 'M' THEN 1 ELSE 0 END)
     
    FROM	TABLE1 as a LEFT JOIN TABLE2 as b	ON  B.ACCOUNT = a.ACCOUNT
    						AND B.DATE2 = a.DATE - 365 AND a.DATE
    						AND B.NAME = 'M'
     
    GROUP BY DATE, ACCOUNT

    Pour résumer:
    De ma table1, je dois vérifier, avec la table2, si durant l'année, le compte de ma table 1 a eu le nom 'M' au moins une fois dans l'année.
    Si oui, 1, si non 0.

    Le soucis, c'est que j'aimerai qu'il arrête de rechercher (pour gagner du temps) dès que la condition a été vérifiée, ne fut-ce qu'une seule fois dans l'année.


    Voici un autre code que j'utilise (qui va un rien plus vite)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT	DATE, 
    	ACCOUNT,
    	MAX(CASE WHEN NAME = IS NULL THEN 0 ELSE 1 END)
     
    FROM	TABLE1 as a LEFT JOIN TABLE2 as b	ON  B.ACCOUNT = a.ACCOUNT
    						AND B.NAME = 'M'
    						AND B.DATE2 = (SELECT MAX(DATE2) FROM TABLE2 WHERE ACCOUNT = a.ACCOUNT AND NAME = 'M' AND DATE BETWEEN A.DATE - 365 AND a.DATE)
    Mais ici, j'appelle ma table2 deux fois !
    Or cette table 2 est énorme, d'où mon besoin d'améliorer ce code.


    TOUT serait donc plus simple s'il existait ce fameux TOP 1 dans mon left join..

  9. #9
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    Si j'en referre a vos explications, cette requete serait donc plus en concordance avec votre regle :

    De ma table1, je dois vérifier, avec la table2, si durant l'année, le compte de ma table 1 a eu le nom 'M' au moins une fois dans l'année.
    Si oui, 1, si non 0.

    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
    SELECT 
    	DATE, 
    	ACCOUNT, 
    	CASE WHEN
    		EXISTS (SELECT 
    				1 
    			FROM 
    				TABLE2 B 
    			WHERE 
    				B.ACCOUNT=A.ACCOUNT AND
    				B.DATE BETWEEN A.DATE-365 and A.DATE AND
    				B.NAME='M'
    			) THEN 1 ELSE 0 END
    FROM
    	TABLE1 A
    Dans la connaissance du monde, ceux qui ne savent rien en savent toujours autant que ceux qui n'en savent pas plus qu'eux. (Pierre Dac)

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 190
    Points : 59
    Points
    59
    Par défaut
    Merci.
    Cette option en est une autre.

    Maintenant, je dois faire mes test pour voir la vitesse d'excecution entre ces méthodes.

    Une idée ?

    Merci

  11. #11
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    une idée a propos de quoi ? de vos test ?

    Regardez les plans d'execution
    Dans la connaissance du monde, ceux qui ne savent rien en savent toujours autant que ceux qui n'en savent pas plus qu'eux. (Pierre Dac)

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 190
    Points : 59
    Points
    59
    Par défaut
    Je n'ai plus le temps de vérifier aujourd'hui.
    Mais je pense que votre solution (Yanika_bzh) semble la plus efficiente en terme de rapidité.

    une idée a propos de quoi ? de vos test ?
    --> Une idée concernant le temps d'execution de la requete selon les 3 méthodes proposées, en sachant que la table2 est vraiment complexe et gourmande..

  13. #13
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    ca depend aussi des indexes que vous avez définis
    Dans la connaissance du monde, ceux qui ne savent rien en savent toujours autant que ceux qui n'en savent pas plus qu'eux. (Pierre Dac)

  14. #14
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Cela peut dépendre aussi du volume à traiter. Une méthode peut être plus efficace qu'une autre au bout d'un certain volume.

    ++

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

Discussions similaires

  1. [AC-2007] TOP 1 dans LEFT JOIN
    Par windmastr26 dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 05/07/2011, 08h42
  2. LEFT JOIN avec Oracle 8i ne va pas... doit utiliser (+)
    Par loikiloik dans le forum Langage SQL
    Réponses: 10
    Dernier message: 21/04/2004, 16h38
  3. Interbase et left join
    Par Zog dans le forum Bases de données
    Réponses: 4
    Dernier message: 23/03/2004, 08h55
  4. Non coincident MySQL (Left Join)
    Par Remiguel dans le forum Requêtes
    Réponses: 6
    Dernier message: 03/11/2003, 21h25
  5. Export d'une vue avec LEFT JOIN
    Par schnourf dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 22/05/2003, 13h57

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