Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用SQL Server选择top返回的输出与选择不同*_Sql_Sql Server_Select_Sql Order By_Concat - Fatal编程技术网

使用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