Pourquoi il n'y a pas de "choisir" ou "sélectionner bas" dans SQL Server comme il est `select top"?
Je sais que cela peut sembler une question stupide, mais s'il vous plaît garder avec moi.
Dans SQL server, nous avons
SELECT TOP N ...
maintenant que nous pouvons obtenir les n premières lignes dans ordre croissant (par défaut), c'est cool. Si nous voulons que les enregistrements triés sur n'importe quelle autre colonne, nous venons de l'indiquer dans la clause order by, quelque chose comme ça...
SELECT TOP N ... ORDER BY [ColumnName]
Encore plus cool. Mais que faire si je veux le last
ligne? Je viens de d'écrire quelque chose comme ceci...
SELECT TOP N ... ORDER BY [ColumnName] DESC
Mais il y a une légère préoccupation avec qui. Je l'ai dit préoccupation et pas question car il n'est pas vraiment un problème. De cette manière, j'ai pu obtenir la dernière ligne en fonction de cette colonne, mais si je veux la dernière ligne qui a été inséré. Je sais que sur SCOPE_IDENTITY
, IDENT_CURRENT
et @@IDENTITY
, mais imaginez un heap
(une table sans clustered index
) sans aucune colonne d'identité et des accès multiples à partir de nombreux endroits (veuillez de ne pas aller dans cette trop comment et quand ces multiples opération se passe, cela ne concerne pas la chose principale). Donc, dans ce cas, il ne semble pas être un facile façon à trouver la ligne qui a été réellement inséré dernier. Certains pourraient répondre à ce que
Si vous faites un select * from [table] la dernière ligne affichée dans le sql de la fenêtre de résultat sera le dernier inséré.
À rien de penser à ce sujet, ce n'est pas réellement le cas, du moins pas toujours, et que vous pouvez toujours compter sur (msdn, veuillez lire la Advanced Scanning
section).
De sorte que la question se résume à ceci, comme dans le titre lui-même. Pourquoi ne pas SQL Server ont un
SELECT LAST
ou dire
SELECT BOTTOM
ou quelque chose comme ça, où nous n'avons pas à spécifier le Order By
et puis, elle donnerait l' dernier enregistrement inséré dans le tableau au moment de l'exécution de la requête (encore une fois je ne vais pas dans les détails sur comment ce résultat en cas de non validées à des lectures ou des lectures fantômes).
Mais si malgré tout, quelqu'un affirme que nous ne pouvons pas parler de ce sujet sans parler de ces niveaux de lecture, alors, pour eux, nous avons pu la faire se comporter de la même manière que TOP
travail mais tout le contraire. Mais si votre argument est alors nous n'avons pas besoin que nous pouvons toujours faire
SELECT TOP N ... ORDER BY [ColumnName] DESC
alors je ne sais vraiment pas quoi dire ici. Je savoir nous pouvons le faire, mais il y a aucune relation basée sur la raison, ou sémantique basée sur la raison, ou pour une autre raison en raison de laquelle nous n'avons pas ou ne pouvez pas avoir ce SELECT LAST/BOTTOM
. Je ne suis pas à la recherche de façon à ne Order By
, je suis à la recherche de raisons pour lesquelles le faire ne l'avez pas ou ne pouvez pas l'avoir.
Supplémentaire
Je ne sais pas trop comment NOSQL fonctionne, mais j'ai travaillé (un peu) avec mongodb
et elastic search
, et, là aussi, ne semble pas être quelque chose de ce genre. Est la raison pour laquelle ils n'ont pas, c'est parce que personne n'a jamais eu avant, ou est-ce pour une raison pas plausible?
Mise à JOUR
Je ne pas besoin de savoir que j'ai besoin de spécifier l'ordre décroissant ou pas. Veuillez lire la question et de comprendre mon inquiétude avant de répondre ou de commenter. Je sais comment vais-je obtenir la dernière ligne. Ce n'est même pas la question, la question principale se résume à la pourquoi pas select last/bottom
comme il l'homologue.
Mise à JOUR 2
Après les réponses de Vladimir et Pieter, je voulais juste mettre à jour que je sais que la commande n'est pas garanti si je fais un SELECT TOP
sans ORDER BY
. Je sais ce que j'ai écrit plus tôt dans la question pourrait faire une impression que je ne sais pas qui est le cas, mais si vous cherchez juste un plus bas, je ont donné un lien pour msdn et ont indiqué que la SELECT TOP
sans ORDER BY
ne garantit toute commande. Donc merci de ne pas l'ajouter à votre réponse que ma déclaration de mal, comme je l'ai déjà précisé que moi-même après une couple de lignes (où j'ai fourni le lien vers msdn
).
- Lorsque vous sélectionnez des données d'une table dans SQL, il n'y a pas de garantie de la commande, sauf si vous spécifiez
ORDER BY
. donc pour obtenir précis selon vos besoins, vous avez besoin de faire unTOP N
avecORDER BY somecol
. Pour obtenir les N dernières lignes comme vous l'avez mentionné que vous venez de modifier l'ordre deORDER BY somecol desc
- Sir serait vous s'il vous plaît lire la question avant de commenter? Avez-vous encore rien lu ou elle?
- SQL n'est pas intéressé à quand une ligne a été insérée, si vous vous avez besoin d'un horodatage sur la table.
- Je l'ai fait et c'est le cœur du problème. Même si la table est un segment ou d'un index cluster a, lorsque vous faites un select sans une ordonnance il n'y a aucune garantie que les lignes seront dans un ordre spécifique (de l'ordre de l'insertion ou de quoi que ce soit).
- connect.microsoft.com/SQLServer? 🙂
- De la même manière vous ne pouvez pas faire un
SELECT LAST/SELECT BOTTOM
il n'y a pas deSELECT TOP
qui obtient la première ligne insérée dans la façon dont vous parliez à l'aide deSELECT LAST
... Vous avez besoin d'un horodatage - Je pense que l'OP est la recherche d'une sorte de fonction qui donne
LAST
ouBOTTOM
enregistrement inséré et pour voir si il y a un besoin pour qu'il soit disponible dans SQL Server. Il ne plaide pas pour rien que vous êtes en train de dire, comme il l'a dit lui-même dans la question. - Uniquement les développeurs de Microsoft (ou les chefs de produit) peut répondre à pourquoi ils n'ont pas une telle fonctionnalité. Il est inutile de demander ici.
- Comme @MarkSinkinson commentaire aludes, vous êtes allé de mal en début de votre question, vous vous référez à
TOP N
sansORDER BY
que "nous pouvons obtenir les n premières lignes dans l'ordre croissant" - mais ce n'est pas le cas. Vous obtenez à n lignes. C'est tout. Vous n'êtes pas garanti qu'ils sont les n premières lignes. la première et la dernière ont pas de sens en SQL, à moins de fournir unORDER BY
. - le haut et le dernier est le même, ok?
- J'ai besoin pour cela - je veux la liste les données dans l'ordre croissant (j'ai une commande par l') mais qui ne veulent pas montrer les 5 dernières lignes. Je suis à l'aide d'un système de communication où l'sélectionnez doit retourner les lignes de données à afficher, dans l'ordre souhaité. Si utile question (et apparemment pas de solution facile).
Vous devez vous connecter pour publier un commentaire.
Vous pouvez penser à elle comme ça.
SELECT TOP N
sansORDER BY
retourne certainsN
lignes, ni le premier, ni le dernier, juste certains. Les lignes qui il renvoie n'est pas défini. Vous pouvez exécuter le même état 10 fois et bénéficiez de 10 différents jeux de lignes à chaque fois.Donc, si le serveur a une syntaxe
SELECT LAST N
, puis le résultat de cette instruction sansORDER BY
serait encore indéfini, ce qui est exactement ce que vous obtenez avec l'existantSELECT TOP N
sansORDER BY
.Vous l'avez souligné dans votre question que vous connaissez et comprenez ce que j'ai écrit ci-dessous, mais je vais encore le garder pour le rendre clair pour tout le monde la lecture de ce plus tard.
Votre première phrase dans la question
n'est pas correct. Avec
SELECT TOP N
sansORDER BY
vous obtenez N "aléatoire" des lignes. Eh bien, pas vraiment au hasard, le serveur ne saute pas au hasard à partir de la ligne à la ligne de but. Il choisit quelques déterministe de numériser à travers la table, mais il pourrait y avoir de nombreuses façons différentes pour l'analyse de la table et le serveur est libre de modifier le chemin choisi quand il veut. C'est ce que l'on entend par "undefined".Le serveur ne suit pas l'ordre dans lequel les lignes ont été insérées dans la table, donc encore une fois votre hypothèse que les résultats de
SELECT TOP N
sansORDER BY
sont déterminés par l'ordre dans lequel les lignes ont été insérées dans la table n'est pas correct.Donc, la réponse à votre question finale
est:
ORDER BY
résultats deSELECT LAST N
serait exactement le même que les résultats deSELECT TOP N
- undefined.ORDER BY
résultat deSELECT LAST N ... ORDER BY X ASC
est exactement le même que le résultat deSELECT TOP N ... ORDER BY X DESC
.Donc, il est inutile d'avoir deux mots-clés qui font la même chose.
Il est un bon point dans le Pieter de réponse: le mot
TOP
est quelque peu trompeur. Il signifie vraimentLIMIT
l'ensemble des résultats à un certain nombre de lignes.Par la façon dont, depuis SQL Server 2012, ils ont ajouté le support pour la norme ANSI
OFFSET
:Ici l'ajout d'un autre mot-clé a été justifiée, elle est conforme à la norme ANSI ET il ajoute des fonctionnalités importantes - la pagination, ce qui n'existait pas avant.
Je tiens à remercier @Razort4x ici pour fournir un très bon lien pour MSDN dans sa question. La "Numérisation Avancée" de la section il y a un excellent exemple de mécanisme appelé "merry-go-round de la numérisation", ce qui explique pourquoi l'ordre des résultats retournés par un
SELECT
déclaration ne peut être garantie sans uneORDER BY
clause.Ce concept est souvent mal compris et j'ai vu beaucoup de question, ici, de SORTE que serait grandement bénéfique si elles avaient un devis à partir de ce lien.
La réponse à votre question
est:
Le diable est dans les détails que vous souhaitez omettre. Pour savoir quel est le dossier a été le "dernier insérées dans le tableau au moment de l'exécution de la requête" (et en un peu cohérente/manière non-aléatoire) le serveur aurait besoin de garder une trace de cette information en quelque sorte. Même si il est possible dans tous les scénarios de plusieurs simultanément transactions en cours d'exécution, il est plus que probable coûteux du point de vue des performances. Pas tous les
SELECT
serait de demander cette information (en fait très peu ou rien du tout), mais la surcharge de suivi de cette information serait toujours là.De sorte que vous pouvez penser de cette façon: par défaut, le serveur ne prend pas en faire quelque chose de spécifique à savoir/garder une trace de l'ordre dans lequel les lignes ont été insérées, car il affecte les performances, mais si vous avez besoin de savoir que vous pouvez utiliser, par exemple,
IDENTITY
colonne. Microsoft pourrait avoir conçu le moteur du serveur d'une façon telle qu'il a fallu uneIDENTITY
colonne de chaque table, mais ils l'ont fait en option, ce qui est bon à mon avis. Je sais mieux que le serveur de mes tables besoinIDENTITY
colonne et qui ne le font pas.Résumé
Je voudrais résumer que vous pouvez regarder
SELECT LAST
sansORDER BY
de deux façons différentes.1) Lorsque vous vous y attendez
SELECT LAST
à se comporter en accord avec lesSELECT TOP
. Dans ce cas, le résultat n'est pas défini pour les deuxLAST
etTOP
, c'est à dire le résultat est effectivement la même. Dans ce cas, il se résume à (ne pas) avoir un autre mot clé. Le langage des développeurs (langage T-SQL dans ce cas) sont toujours réticents à ajouter des mots clés, à moins qu'il y a de bonnes raisons pour cela. Dans ce cas, il est clairement évitable.2) Lorsque vous vous y attendez
SELECT LAST
à se comporter comme desSELECT LAST INSERTED ROW
. Ce qui devrait, par ailleurs, d'étendre les mêmes attentes àSELECT TOP
à se comporter comme desSELECT FIRST INSERTED ROW
ou ajouter de nouveaux mots clésLAST_INSERTED
,FIRST_INSERTED
à garder existantes mot-cléTOP
intacte. Dans ce cas, il revient à la performance et la charge supplémentaire d'un tel comportement. Au moment où le serveur vous permet d'éviter cette pénalité de performances si vous n'avez pas besoin de cette information. Si vous n'en avez pas besoinIDENTITY
est une assez bonne solution si vous l'utilisez avec soin.Il n'y a pas de sélectionner la dernière, car il n'est pas nécessaire pour cela. Envisager un "select top 1 * from table" . Top 1 vous obtenir la première ligne qui est retourné. Et puis le processus s'arrête.
Mais il n'y a aucune garantie à propos de la commande si vous ne spécifiez pas une commande par. Il peut donc aussi bien être n'importe quelle ligne dans le jeu de données que vous obtenez en retour.
Maintenant faire un "select dernier 1 * from table". Maintenant, la base de données à traiter toutes les lignes afin de vous obtenir le dernier.
Et parce que la commande est non-déterministe, il peut aussi bien être le même résultat que de le "top 1".
Voir maintenant où le problème vient? Sans ordonnance en haut et la dernière sont les mêmes, seul le "dernier" prendra plus de temps. Et à l'ordre, il n'y a vraiment seulement besoin de haut.
Ce que vous dites ici est totalement faux et absolument PAS comment ça marche. Il n'y a pas de garantie sur l'ordre que vous obtenez. Ordre croissant sur ce ?
Essayer ce code ligne par ligne et voir ce que vous obtenez avec le dernier "select top 1".....vous obtenez dans ce cas, le dernier enregistrement inséré.
mise à jour
Je pense que vous comprenez que "select top 1 * from table" signifie en gros: "Sélectionner une ligne au hasard à partir de la table".
Donc, ce serait la dernière signifie? "Sélectionner la dernière ligne aléatoire à partir de la table?" Ne serait pas la dernière ligne aléatoire à partir d'un tableau du point de vue conceptuel la même chose que de dire tout 1 ligne au hasard à partir de la table? Et si c'est vrai, le haut et le dernier sont les mêmes, donc il n'est pas nécessaire pour la dernière.
Mise à jour 2
Avec le recul, j'ai été plus heureux avec la syntaxe mysql utilise : LIMITE.
Top ne veut rien dire sur la commande, c'est seulement là pour spécifier le nombre de lignes à retourner.
Les raisons pour lesquelles
SELECT LAST_INSERTED
n'a pas de sens.Il ne peut pas être facilement appliquée à la non-tables heap.
Tas de données peuvent être déplacées librement par le SGBD de sorte que ceux de "naturel" de l'ordre est sujet à changement. Pour garder le système a besoin de quelque mécanisme supplémentaire qui semble être un inutile gaspillage.
Si vraiment désiré, il peut être simulé par l'ajout de certains " auto-incrémentation de la colonne.
SQL Server est arbitraire, sauf indication contraire. Il est mis en fonction, par conséquent, vous doit définir ce que votre jeu de est. Corriger
SCOPE_IDENTITY()
est la bonne façon de capturer le dernier enregistrement inséré, ou leOUTPUT
clause. Pourquoi voudriez-vous faire insère sur un segment de mémoire que vous avez besoin de référence chronologique, de toute façon?? C'est super mauvaise conception de base de données.SELECT LAST/BOTTOM
, et je n'ai jamais demandé au sujet de conception de base de données, c'est même pas un vrai scénario, et ni est la question que vous pose cette question.because the situation shouldn't exist
ce situation? Les détails/scénario que j'ai ajouté sont hypothétiques. Pensez-vous vraiment votre réponse surSCOPE_IDENTITY
etOUTPUT
clauses répond à ma question d'origine, l'une dans le titre et ce que j'ai aussi ajouté de nouveau dans la partie de mise à jour?SELECT LAST
quoi? C'est trop ambigu. J'espère que vous comprenez mon point de vue et ça aide.