Sélection uniquement de la première ligne d'une table associée dans les jointures SQL
Les jointures de bases de données récupèrent souvent plusieurs lignes correspondantes à partir de tables associées. Cet article traite du scénario dans lequel vous devez limiter la jointure à une seule ligne par enregistrement parent, même s'il existe plusieurs correspondances. Cela évite les résultats en double dans le résultat de votre requête.
Le défi
Considérons deux tableaux : Orders
et LineItems
. En règle générale, une campagne comporte un seul élément de campagne, mais certaines campagnes peuvent en comporter plusieurs. Lors de l'affichage des détails de la commande, il est crucial d'afficher un seul élément de campagne par commande, sinon les doublons encombrent les résultats.
Approche initiale (et son échec)
Une tentative naïve d'utilisation de TOP 1
dans la jointure échoue directement car la requête interne ne peut pas accéder aux colonnes de la table externe (comme OrderID
).
La solution : CROSS APPLY et INNER JOIN
L'approche la plus efficace utilise CROSS APPLY
(disponible dans SQL Server 2005 et versions ultérieures) ou un INNER JOIN
intelligent pour les anciennes versions.
Utilisation de CROSS APPLY (SQL Server 2005 et versions ultérieures)
CROSS APPLY
génère un ensemble de lignes pour chaque ligne de la table externe, permettant une sous-requête corrélée. Cette sous-requête filtre et sélectionne ensuite une seule ligne de la table associée.
<code class="language-sql">SELECT Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description FROM Orders CROSS APPLY ( SELECT TOP 1 LineItems.Quantity, LineItems.Description FROM LineItems WHERE LineItems.OrderID = Orders.OrderID ) LineItems2</code>
Utilisation d'INNER JOIN (SQL Server antérieur à 2005)
Pour les anciennes versions de SQL Server dépourvues de CROSS APPLY
, un INNER JOIN
avec une sous-requête permet d'obtenir le même résultat :
<code class="language-sql">SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description FROM Orders INNER JOIN LineItems ON LineItems.LineItemGUID = ( SELECT TOP 1 LineItemGUID FROM LineItems WHERE OrderID = Orders.OrderID )</code>
Remarque importante sur le déterminisme :
La clause TOP 1
est intrinsèquement non déterministe sans clause ORDER BY
. Pour garantir des résultats cohérents (c'est-à-dire, en sélectionnant toujours le même "premier" élément de ligne), ajoutez une clause ORDER BY
dans la requête interne (par exemple, ORDER BY LineItems.SomeColumn
). Cela garantit une sélection prévisible de l'élément de campagne.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!