Je vais utiliser un exemple concret, mais hypothétique.
Chaque commande ne comporte normalement qu'un seul élément de campagne :
Ordres:
OrderGUID OrderNumber
========= ============
{FFB2...} STL-7442-1
{3EC6...} MPT-9931-8A
LineItems:
LineItemGUID Order ID Quantity Description
============ ======== ======== =================================
{098FBE3...} 1 7 prefabulated amulite
{1609B09...} 2 32 spurving bearing
Mais il y aura parfois une commande avec deux éléments de campagne:
LineItemID Order ID Quantity Description
========== ======== ======== =================================
{A58A1...} 6,784,329 5 pentametric fan
{0E9BC...} 6,784,329 5 differential girdlespring
Normalement, lors de la présentation des commandes à l'utilisateur:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
Je veux montrer l'article unique sur la commande. Mais avec cette commande occasionnelle contenant deux (ou plus) articles, les commandes semblent être dupliquées :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 spurving bearing
KSG-0619-81 5 panametric fan
KSG-0619-81 5 differential girdlespring
Ce que je veux vraiment, c'est que SQL Server n'en choisisse qu'un , car ce sera suffisant :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan
Si je deviens aventureux, je pourrais montrer à l'utilisateur des points de suspension pour indiquer qu'il y en a plus d'un:
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan, ...
La question est donc de savoir comment
- éliminer les lignes "en double"
- joindre uniquement à l'une des lignes, pour éviter la duplication
Premier essai
Ma première tentative naïve a été de ne rejoindre que les éléments de campagne " TOP 1 ":
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN (
SELECT TOP 1 LineItems.Quantity, LineItems.Description
FROM LineItems
WHERE LineItems.OrderID = Orders.OrderID) LineItems2
ON 1=1
Mais cela donne l'erreur:
La colonne ou le préfixe «Commandes» ne
correspond pas au nom de table ou au nom d'alias
utilisé dans la requête.
Vraisemblablement parce que la sélection interne ne voit pas la table externe.
la source
group by
?group by
nécessiterait de répertorier toutes les autres colonnes, à l'exception de celle où vous ne voulez pas de doublons. SourceRéponses:
Dans SQL Server 2005 et supérieur, vous pouvez simplement remplacer
INNER JOIN
parCROSS APPLY
:Veuillez noter que
TOP 1
sansORDER BY
n'est pas déterministe: cette requête vous donnera un élément de campagne par commande, mais il ne sera pas défini lequel.Plusieurs appels de la requête peuvent vous donner différents éléments de campagne pour le même ordre, même si le sous-jacent n'a pas changé.
Si vous voulez un ordre déterministe, vous devez ajouter une
ORDER BY
clause à la requête la plus interne.la source
CROSS APPLY
à la placeINNER JOIN
et à laOUTER APPLY
placeLEFT JOIN
(le même queLEFT OUTER JOIN
).Je sais que cette question a reçu une réponse il y a un certain temps, mais lorsqu'il s'agit de grands ensembles de données, les requêtes imbriquées peuvent être coûteuses. Voici une solution différente où la requête imbriquée ne sera exécutée qu'une seule fois, au lieu de pour chaque ligne renvoyée.
la source
Vous pourriez faire:
Cela nécessite un index (ou une clé primaire) sur
LineItems.LineItemID
et un index surLineItems.OrderID
ou ce sera lent.la source
LineItems.LineItemID = null
et supprime complètement les ordres d'entité de gauche du résultat.La réponse @Quassnoi est bonne, dans certains cas (surtout si la table externe est grande), une requête plus efficace pourrait être d'utiliser des fonctions fenêtrées, comme ceci:
Parfois, il vous suffit de tester quelle requête donne de meilleures performances.
la source
, Autre approche utilisant une expression de table commune:
ou, à la fin, vous aimeriez peut-être afficher toutes les lignes jointes?
version séparée par des virgules ici:
la source
À partir de SQL Server 2012 et versions ultérieures, je pense que cela fera l'affaire:
la source
Les sous-requêtes corrélées sont des sous-requêtes qui dépendent de la requête externe. C'est comme une boucle for en SQL. La sous-requête s'exécutera une fois pour chaque ligne de la requête externe:
la source
EDIT: peu importe, Quassnoi a une meilleure réponse.
Pour SQL2K, quelque chose comme ceci:
la source
Ma façon préférée d'exécuter cette requête est avec une clause n'existe pas. Je pense que c'est le moyen le plus efficace d'exécuter ce type de requête:
Mais je n'ai pas testé cette méthode par rapport aux autres méthodes suggérées ici.
la source
J'ai essayé la croix, ça marche bien, mais ça prend un peu plus de temps. Colonnes de ligne ajustées pour avoir un groupe max et ajouté qui a gardé la vitesse et supprimé l'enregistrement supplémentaire.
Voici la requête ajustée:
la source
essaye ça
la source