J'ai une procédure stockée qui n'a pas été créée par moi.

Dans certaines procédures stockées, il existe des jointures imbriquées que j'ai du mal à comprendre.

Quelle serait la manière la plus simple de l'écrire pour comprendre la logique? Et aussi pourquoi ceux-ci sont-ils utilisés? Pour améliorer uniquement les performances?

SELECT *
FROM      
    dbo.tblQuotes AS tblQuotes_1 
LEFT OUTER JOIN
    dbo.lstLines ON tblQuotes_1.LineGUID = dbo.lstLines.LineGUID 
RIGHT OUTER JOIN
    dbo.tblUsers 
RIGHT OUTER JOIN
    dbo.tblQuotes 
RIGHT OUTER JOIN
    dbo.tblClaims_Claim ON dbo.tblQuotes.ControlNo = dbo.tblClaims_Claim.ControlNo 
RIGHT OUTER JOIN
    dbo.tblNoteEntries 
LEFT OUTER JOIN
    dbo.tblNoteRecipients ON dbo.tblNoteEntries.ID = dbo.tblNoteRecipients.EntryGUID 
INNER JOIN
    dbo.tblNoteDiaries ON dbo.tblNoteEntries.ID = dbo.tblNoteDiaries.EntryGUID 
INNER JOIN
    dbo.tblNoteEntities ON dbo.tblNoteEntries.NoteGUID = dbo.tblNoteEntities.NoteGUID 
INNER JOIN
    dbo.tblNoteStore ON dbo.tblNoteEntries.NoteGUID = dbo.tblNoteStore.ID 
                     AND dbo.tblNoteDiaries.NoteGUID = dbo.tblNoteStore.ID 
                     AND dbo.tblNoteEntities.NoteGUID = dbo.tblNoteStore.ID 
INNER JOIN
    dbo.lstNoteTypes ON dbo.tblNoteStore.Type = dbo.lstNoteTypes.NoteTypeID 
       ON dbo.tblClaims_Claim.ClaimGuid = dbo.tblNoteEntities.AssociatedEntityGUID 
       ON dbo.tblUsers.UserGUID = dbo.tblNoteRecipients.UserGUID 
       ON tblQuotes_1.ControlGuid = dbo.tblNoteEntities.ControlGuid 
LEFT OUTER JOIN
    dbo.tblMaxQuoteIDs ON tblQuotes_1.QuoteID = dbo.tblMaxQuoteIDs.MaxQuoteID 
LEFT OUTER JOIN
    dbo.tblInsureds ON dbo.tblNoteEntities.AssociatedEntityGUID = dbo.tblInsureds.InsuredGUID   
1
Serdia 17 janv. 2017 à 02:47

2 réponses

Meilleure réponse

Si la lisibilité est votre objectif, il convient de noter que vous n'avez pas du tout besoin d'imbrication ou de RIGHT JOIN. Le suivant

  • est mathématiquement équivalent
  • lit systématiquement de gauche à droite (en supposant que c'est la façon dont vous aimez lire)
  • N'a pas de nidification
  • N'a pas de jointures droites
  • A moins de caractères et de lignes inutiles

     SELECT *
      FROM dbo.tblNoteStore              nt_str
               JOIN dbo.lstNoteTypes     nt_typ ON nt_str.[Type] = nt_typ.NoteTypeID
               JOIN dbo.tblNoteDiaries   nt_dia ON nt_str.ID = nt_dia.NoteGUID
               JOIN dbo.tblNoteEntities   entit ON nt_str.ID = entit.NoteGUID
               JOIN dbo.tblNoteEntries    entri ON nt_str.ID = entri.NoteGUID
                                                   and nt_dia.EntryGUID = entri.ID 
                                                   and entit.NoteGUID = entri.NoteGUID
          LEFT JOIN dbo.tblNoteRecipients recip ON entri.ID = recip.EntryGUID
          LEFT JOIN dbo.tblUsers            usr ON recip.UserGUID = usr.UserGUID
          LEFT JOIN dbo.tblInsureds       insur ON entit.AssociatedEntityGUID = insur.InsuredGUID
          LEFT JOIN dbo.tblClaims_Claim   claim ON entit.AssociatedEntityGUID = claim.ClaimGUID
          LEFT JOIN dbo.tblQuotes         qts_1 ON entit.ControlGUID = qts_1.ControlGUID
          LEFT JOIN dbo.lstLines          lines ON qts_1.LineGUID = lines.LineGUID
          LEFT JOIN dbo.tblMaxQuoteIDs   max_qt ON qts_1.QuoteID = max_qt.MaxQuoteId
          LEFT JOIN dbo.tblQuotes         qts_2 ON claim.ControlNo = qts_2.ControlNo 
          ;
     
1
DatumPoint 17 janv. 2017 à 12:48

Je transforme généralement la liste en une liste indentée, comme si les différentes jointures étaient des instructions IF imbriquées. Par exemple:

SELECT *
FROM dbo.tblQuotes AS tblQuotes_1 
LEFT OUTER JOIN dbo.lstLines 
    ON tblQuotes_1.LineGUID = dbo.lstLines.LineGUID 
RIGHT OUTER JOIN dbo.tblUsers 
    RIGHT OUTER JOIN dbo.tblQuotes 
        RIGHT OUTER JOIN dbo.tblClaims_Claim 
            ON dbo.tblQuotes.ControlNo = dbo.tblClaims_Claim.ControlNo 
        RIGHT OUTER JOIN dbo.tblNoteEntries 
            LEFT OUTER JOIN dbo.tblNoteRecipients 
                ON dbo.tblNoteEntries.ID = dbo.tblNoteRecipients.EntryGUID 
            INNER JOIN dbo.tblNoteDiaries 
                ON dbo.tblNoteEntries.ID = dbo.tblNoteDiaries.EntryGUID 
            INNER JOIN dbo.tblNoteEntities 
                ON dbo.tblNoteEntries.NoteGUID = dbo.tblNoteEntities.NoteGUID 
            INNER JOIN dbo.tblNoteStore 
                ON dbo.tblNoteEntries.NoteGUID = dbo.tblNoteStore.ID 
                AND dbo.tblNoteDiaries.NoteGUID = dbo.tblNoteStore.ID 
                AND dbo.tblNoteEntities.NoteGUID = dbo.tblNoteStore.ID 
            INNER JOIN dbo.lstNoteTypes 
                ON dbo.tblNoteStore.Type = dbo.lstNoteTypes.NoteTypeID 
            ON dbo.tblClaims_Claim.ClaimGuid = dbo.tblNoteEntities.AssociatedEntityGUID 
        ON  dbo.tblUsers.UserGUID = dbo.tblNoteRecipients.UserGUID 
    ON tblQuotes_1.ControlGuid = dbo.tblNoteEntities.ControlGuid 
LEFT OUTER JOIN dbo.tblMaxQuoteIDs 
    ON tblQuotes_1.QuoteID = dbo.tblMaxQuoteIDs.MaxQuoteID 
LEFT OUTER JOIN dbo.tblInsureds 
    ON dbo.tblNoteEntities.AssociatedEntityGUID = dbo.tblInsureds.InsuredGUID

Je déplace ensuite l'une des conditions ON hors de place vers leur emplacement correct, si je peux le faire sans détruire la logique de la requête. Dans ce cas, je ne peux pas le faire sans une analyse significative.

REMARQUE: Je déteste honnêtement ce type de séquence de jointure, et si vous connaissez les tables et les relations, vous pouvez probablement la réorganiser pour qu'elle devienne une simple liste de jointures au lieu de la structure de jointure imbriquée étrange. Mais cela dépend de deux choses importantes:

  1. Cela a-t-il été fait pour optimiser les performances de la requête?

Même maintenant, dans la dernière version de SQL Server avec laquelle j'ai travaillé (2014), certaines requêtes peuvent être optimisées en déplaçant les références de table dans votre liste JOIN. Si c'est la raison pour laquelle la liste a été réorganisée dans cette structure imbriquée, vous pourriez sérieusement endommager les performances en annulant l'organisation spéciale. Bien sûr, si cela a été écrit dans une version antérieure de SQL Server à l'origine, vous souhaiterez peut-être démêler ces jointures pour voir si l'optimiseur de requête gère désormais correctement cette structure.

  1. Cela a-t-il été fait à cause d'une faille dans la normalisation des données qui nécessite en fait que la liste JOIN imbriquée fonctionne du tout?

Ne sous-estimez jamais la stupidité de vos prédécesseurs (pour des exemples, rendez-vous sur The Daily WTF et parcourez le site pendant quelques minutes.) Si les structures de données peuvent être liées de manière à nécessiter des JOIN gênantes et dénormalisées, elles seront liées de telle manière. Je n'ai pas réellement vu cette raison validée, mais je sais dans mon instinct qu'une structure de données quelque part l'exige.

2
Laughing Vergil 17 janv. 2017 à 01:04