SQL Top 子句与 order by 子句

问题描述

我对 SQL 有点陌生,我想用 TOP 子句和 order by 子句编写查询。

所以,为了返回我在查询下面写的所有记录

select PatientName,PlanDate as Date,* from    OPLMLA21..Exams  order
by PlanDate desc

而且我需要来自同一个查询的前几个元素,所以我将查询修改为

select top(5) PatientName,* from    OPLMLA21..Exams 
order by PlanDate desc

根据我的理解,它将给出上一个查询的前 5 个结果,但我在那里看到了歧义。我附上了查询结果的截图。

可能是我的理解有误,我读了很多但无法理解这一点,请帮助我。

enter image description here

解决方法

我在 comment 中说明了这一点,但要重复:

TOP (5) 没有给出先前查询的“最佳结果”,不是。它给出了查询中定义的数据集中的前(第一)行。如果有多行具有相同的“等级”,则为该等级返回的行是任意的。因此,例如,对于您的查询,如果您有 100 行都具有相同的 PlanDate 值,那么您得到的 5 行是完全任意的,并且每次运行时都可能不同(包括它们的顺序)说查询。

我所说的任意是指,实际上,SQL Server 可以自由选择返回的任何适用行。 有时这可能在每次运行查询时都是一样的,但幸运的是,这比什么都重要。随着您的数据库变大,您有更多用户查询数据,您涉及连接,诸如锁、索引、并行等都会影响 SQL Server 处理所述数据的“顺序”,并且 产生歧义的 TOP 子句。

以下面的示例数据为例:

ID | SomeDate
---|---------
1  |2020-01-01
2  |2020-01-01
3  |2020-01-01
4  |2020-01-01
5  |2020-01-01
6  |2020-01-02

现在,如果我使用 TOP (2)ORDER BY 子句对该表运行 SomeDate DESC,您会期待什么。嗯,当然,您希望返回“最后”行(ID6),但是下一行呢?其他 5 行都具有相同的 SomeDate 值。也许,因为您认为表中的数据是预先排序的,所以您可能期望 5 的值为 ID 的行。如果我告诉你在 CLUSTERED INDEX 上有一个 ID ASC 怎么办?这很可能最终意味着返回值为 1 的行。如果 SomeDate DESC 上也有索引怎么办?

如果该表的大小为 10,000 行,并且您还有一个指向另一个表的 JOIN,该表也有一个 CLUSTERED INDEX,并且某些用户正在执行具有某些特定行锁定的查询,该怎么办在您运行查询时打开?那么你会期待什么?

如果您的 ORDER BY 不够具体以确保每一行具有不同的排序位置,SQL Server 将以任意顺序返回其他行,并且当与 TOP 混合时表示“顶部”行也将是任意的。

旁注:我注意到在您的图像(似乎是 SSMS)中,您的“日期”采用 yyyyMMdd 格式。这强烈暗示您将日期值存储为 varcharint 类型。这是一个设计缺陷,需要修复。有 6 种日期和时间数据类型,其中 5 种远优于使用字符串和数字数据类型来存储数据。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...