2017-06-28 2 views
2

Est-ce que "TOP 1" est un substitut fiable pour les fonctions d'agrégation telles que MIN() et MAX() ..? Ci-dessous est une requête de base dans Access 2007, pour déterminer la première fois qu'un client a commandé un certain produit pendant un certain mois. Le système de SGBD n'est probablement pas pertinent, car cette question pourrait s'appliquer à n'importe quel système.Dans une requête SQL, "TOP 1" est-il un substitut fiable pour les fonctions d'agrégation telles que MIN() ou MAX() ..?

Dans cette requête, "TOP 1" est utilisé en combinaison avec ORDER BY dans le champ de date. Cela renvoie un enregistrement, qui est le plus ancien par date. Mais ... est-ce correct? Qu'est-ce qui peut mal tourner ..? Y a-t-il un meilleur moyen ..?

SELECT TOP 1 DAACCT, DAITEM, DAQTY, DAIDAT 

FROM fqlOrdersGrandHistory 

WHERE DAACCT="T7414" AND DAITEM="45234" AND (DAIDAT>=20170501 AND DAIDAT<=20170531) 

ORDER BY DAIDAT; 
+1

_ "Mais ... est-ce correct?" _ Oui, si vous n'avez pas plusieurs enregistrements avec la même date. Mais ce n'est pas la même chose que 'MIN' et' MAX' –

+0

Cela ressemble à un problème XY. Je suppose que vous essayez d'utiliser une fonction d'agrégation mais que d'autres colonnes sont affichées, mais vous ne voulez pas les regrouper? Il existe des moyens de résoudre ce problème. Le fait de commander et d'utiliser select top 1 est une solution de contournement, comme l'a dit Tim, en supposant que vous commandez par valeurs uniques. –

+0

Oui, c'est exactement ça. J'ai une requête qui renvoie un ensemble de factures, et je veux réduire cela à celui avec la date la plus ancienne. Donc, au minimum, j'ai besoin des champs pour le numéro de facture et la date. Si j'utilise MIN() dans ce scénario, cela ne fonctionne pas en raison des numéros de facture différents. Bien que je comprenne que c'est parce que chaque enregistrement et tous ses domaines sont évalués dans leur ensemble, je n'ai pas encore trouvé de solution à ce problème fondamental. – spinjector

Répondre

2

Fiable est un terme subjectif. Oui, TOP 1 vous donnera un résultat, tout comme MAX() ou MIN(). Cela dépend de ce que vous recherchez.

Si vous recherchez uniquement un utilisateur spécifique (comme vous semblez l'être dans ce cas) et que vous le triez par DATE croissant et que vous utilisez TOP 1, vous obtiendrez tous les détails pour cet enregistrement. Cependant, si vous recherchez le premier achat de chaque utilisateur dans la table, alors TOP 1 ne vous donnera que l'information pour la toute première personne qui a passé une commande.

D'autre part, si vous utilisez SELECT DAACCT, MIN(DAIDAT) FROM table GROUP BY DAACCT alors vous obtiendrez l'achat le plus tôt pour chaque utilisateur. Cela suppose que vous stockez le DAIDAT comme format de date avec un composant de temps, pas seulement la valeur de date elle-même. Si vous faites cela, vous vous ouvrez à plusieurs enregistrements possibles. TL; DR: Si vous restez avec le concept de la requête 1) à la recherche d'un utilisateur très spécifique pour 2) un produit très spécifique et 3) vos dates sont stockées comme dates appropriées, TOP 1 sera préférable d'utiliser que une fonction agrégée. Si l'une de ces trois conditions n'est pas remplie, réévaluer.

+0

Ce système stocke les dates sous la forme d'un entier long, au format AAAAMMJJ. Donc, par exemple aujourd'hui serait 20170628. Après avoir discuté de la question avec un collègue, TOP 1 devrait fonctionner. S'il y a plusieurs factures ce jour-là, ce n'est pas grave, choisissez-en une puisque c'est la date que nous recherchons. Le numéro de facture est accessoire et peut être inclus pour référence. – spinjector

+0

Si cela a résolu votre problème, n'oubliez pas de le marquer comme la réponse acceptée. – SandPiper

1

TOP est utilisé pour limiter les lignes extraites et oui, il est très bien, sauf si vous avez plusieurs enregistrements avec les mêmes données. Vous ne savez pas comment il se rapporte à Min() ou Max() ... vous utilisez la fonction d'agrégat Min() ou Max() lorsque vous regroupez les lignes en utilisant Group By. Même si vous ne spécifiez pas un group by groupe se produit sur l'ensemble du résultat

+0

Vous pouvez également utiliser 'MIN' /' MAX' avec 'WHERE' (qu'il a utilisé). Mais bien sûr, ce n'est pas la même chose que «TOP 1» qui choisit les valeurs d'un seul enregistrement alors que «MIN» et «MAX» pourraient choisir les valeurs de différents enregistrements. –

+0

Il existe plusieurs autres couches du problème.Je viens de discuter de la question de l'unicité avec un collègue. Ce que je dois faire est d'obtenir la plus vieille date (s) de la requête, qui m'a été dit pourrait conduire à plusieurs résultats, car nous envoyons dans plusieurs cas plusieurs factures à un client le même jour. Donc ... alors j'ai besoin d'obtenir un de ces nombres et en choisir un avec TOP 1 parce que c'est la date résultante qui est le but de cette requête. Alors maintenant que j'y pense ... je pense que TOP 1 fonctionnera bien pour ça. – spinjector

1

Il est OK si un champ ou une combinaison de champs des champs sélectionnés est unique. Si ce n'est pas le cas, l'ensemble de résultats contiendra tous les enregistrements où le champ ou la combinaison correspond. Pour éviter cela, incluez toujours, disons, un champ de numérotation automatique dans les champs sélectionnés.