使用SQL Server选择top返回的输出与选择不同*
我试图从基于字母和编号格式的数据库中获取使用SQL Server选择top返回的输出与选择不同*,sql,sql-server,select,sql-order-by,concat,Sql,Sql Server,Select,Sql Order By,Concat,我试图从基于字母和编号格式的数据库中获取select top n数据。输出必须先按字母排序,然后按数字排序 当我尝试获取所有数据时(选择*),我得到了正确的输出: select nocust, share from TB_STOCK where share = ’BBCA’ and concat(share, nocust) < ‘ZZZZZZZZ’ order by case when nocust like ‘[a-z]%’ then 0 else 1 end n
select top n
数据。输出必须先按字母排序,然后按数字排序
当我尝试获取所有数据时(选择*
),我得到了正确的输出:
select nocust, share
from TB_STOCK
where share = ’BBCA’
and concat(share, nocust) < ‘ZZZZZZZZ’
order by
case when nocust like ‘[a-z]%’ then 0 else 1 end
nocust | share
-------+--------
a522 | BBCA
b454 | BBCA
k007 | BBCA
p430 | BBCA
q797 | BBCA
s441 | BBCA
s892 | BBCA
u648 | BBCA
v107 | BBCA
4211 | BBCA
6469 | BBCA
6751 | BBCA
我认为错误在concat和order by之间,有人能告诉我如何获得正确的前5名输出,如:
nocust | share
-------+--------
a522 | BBCA
b454 | BBCA
k007 | BBCA
p430 | BBCA
q797 | BBCA
您有一个非常奇怪的
排序依据
——它只确保开头有字母的条目在开头有数字的条目之前排序——但是您不是真正按照值本身排序的。没有特定的orderby
意味着:无法保证行的排序方式—正如您在这里看到的
您需要根据调整您的订单:
ORDER BY
CASE WHEN nocust LIKE '[a-z]%' THEN 1 ELSE 0 END,
nocust
现在您实际上是按nocust
订购的-现在,我很确定,输出将是相同的您有一个非常奇怪的
排序依据-它只确保开头有字母的条目在开头有数字的条目之前排序-但是您不是真正按照值本身排序的。没有特定的orderby
意味着:无法保证行的排序方式—正如您在这里看到的
您需要根据调整您的订单:
ORDER BY
CASE WHEN nocust LIKE '[a-z]%' THEN 1 ELSE 0 END,
nocust
现在您实际上是按nocust
订购的-现在,我非常确定,输出将是相同的您的订购方式不是一个稳定的排序;它将数据大致分为两个类别之一,但没有详细说明如何在类别中对项目进行排序。这意味着在前5个表单中,sqlserver可以自由选择数据访问策略,这意味着它可以在找到5行数据后轻松停止,这些行的数据在
返回0时为情况
假设您有来自SELECT*…的输出。。。按类别订购
Category, Thing
Animal, Cat
Animal, Dog
Animal, Goat
Vegetable, Potato
Vegetable, Turnip
Vegetable, Swede
如果执行选择TOP 2*,则绝对不能保证。。。按类别排序
您将按该顺序获得“猫、狗”。当SQL server在添加新数据后重新调整其索引时,您可以合理地得到今天的“Goat,Dog”和明天的“Cat,Goat”。按类别排列的前2名唯一可以保证的是,只要db中至少有两个动物,并且没有比“动物”的字母顺序早的新类别,您将得到两个动物
这样做是因为对TOP N的优化意味着sqlserver可以在有N行满足条件时提前停止;如果已经发现5行的类别在排序中是第一位的,那么它不需要访问和排序一百万行。让我们想象一下,它可以知道不同的值以及列中这些值的计数,作为其统计信息的一部分,它可以对这些不同的值进行排序,以知道哪些值将首先出现,然后再去查找任何5个随机行,其中有一个值将首先排序,并返回它们。从本质上说,sql server可能会认为“我知道我有3个‘动物’,动物比其他任何东西都重要,用户想要2个。我只需要开始阅读行,在我得到2个动物后停止”,而不是“我会阅读所有东西,对所有百万个动物进行分类,然后选择前2行”
这可能比排序一百万行然后提取第一个X要快得多
为了每次都能得到可重复的结果,您必须通过指定排序条件来保证分类中的内容,从而使排序稳定,排序将一直到没有歧义的地方
在order by中添加更多的列,这样每一行在整个排序中都有一个有保证的位置,然后您的排序将是稳定的,TOP N每次都返回相同的行。要使排序稳定,排序所依据的列集合必须具有唯一的值组合。您可以按20列进行排序,但如果有任何行,其中所有30列都具有相同的值(并且差异仅发生在第21个值上,而您不按该值排序),则不能保证排序顺序。您的排序依据不是稳定的排序;它将数据大致分为两个类别之一,但没有详细说明如何在类别中对项目进行排序。这意味着在前5个表单中,sqlserver可以自由选择数据访问策略,这意味着它可以在找到5行数据后轻松停止,这些行的数据在
返回0时为情况
假设您有来自SELECT*…的输出。。。按类别订购
Category, Thing
Animal, Cat
Animal, Dog
Animal, Goat
Vegetable, Potato
Vegetable, Turnip
Vegetable, Swede
如果执行选择TOP 2*,则绝对不能保证。。。按类别排序
您将按该顺序获得“猫、狗”。当SQL server在添加新数据后重新调整其索引时,您可以合理地得到今天的“Goat,Dog”和明天的“Cat,Goat”。按类别排列的前2名唯一可以保证的是,只要db中至少有两个动物,并且没有比“动物”的字母顺序早的新类别,您将得到两个动物
这样做是因为对TOP N的优化意味着sqlserver可以在有N行满足条件时提前停止;如果已经发现5行的类别在排序中是第一位的,那么它不需要访问和排序一百万行。让我们想象一下,它可以知道不同的值以及列中这些值的计数,作为其统计信息的一部分,它可以对这些不同的值进行排序,以知道哪些值将首先出现,然后再去查找任何5个随机行,其中有一个值将首先排序,并返回它们。从本质上说,sql server可能会认为“我知道我有3个‘动物’,动物比其他任何东西都重要,而用户想要2个。我只需要开始阅读行,在我得到2个动物后停止”,而不是“我会阅读每件事,对所有百万个动物进行分类,然后进行排序”
select top 5 [Name],ProductNumber from Production.Product
order by [Name]
select [Name],ProductNumber from Production.Product
order by case when [name] like '[a]%' then 1 else -1 end
select Top 5 [Name],ProductNumber from Production.Product
order by case when [name] like '[a]%' then 1 else -1 end
Then it pick first n records and display n record quickly.
Sorting was not as expected.
select Top (101) [Name],ProductNumber from Production.Product
order by case when [name] like '[a]%' then 1 else -1 end
;With CTE as(
select nocust, share ,
case when nocust like ‘[a-z]%’ then 0 else 1 end SortCol
from TB_STOCK
where share = ’BBCA’
and concat(share, nocust) < ‘ZZZZZZZZ’
)
select top 5 * from CTE
order by SortCol