在子查询中使用Order By的SQL错误


69

我正在使用SQL Server 2005。

我的查询是:

SELECT (
  SELECT COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
  GROUP BY refKlinik_id
  ORDER BY refKlinik_id
) as dorduncuay

错误:

除非还指定了TOP或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效。

如何ORDER BY在子查询中使用?

Answers:


112

这是您得到的错误(强调我的意思):

除非还指定了TOP或FOR XML否则ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效

那么,如何避免该错误呢?我想,通过指定TOP,将是一种可能性。

SELECT (
  SELECT TOP 100 PERCENT
  COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
  GROUP BY refKlinik_id
  ORDER BY refKlinik_id
) as dorduncuay

6
这不为了通过,如果指定顶部99.99999%的IT工作正常
foz1284

@ foz1284您能否指向一些文档或参考资料来证实这一说法?
Tomalak

14
此处解释的blogs.msdn.com/b/queryoptteam/archive/2006/03/24/560396.aspx与TOP 100%没有顺序,因为当SQL Server评估前99名时,它保证返回所有行需要执行命令以确保它返回正确的行。
foz1284

1
据我了解,这种特殊性仅影响没有聚集索引的表,因此在使用时不会遇到一般问题TOP 100 PERCENT。但是,感谢您的提示,我不知道这一点。
Tomalak

1
我刚刚进行了快速重读,然后看到了您所引用的内容,前几天这对我来说是个问题,因为我正在订购一个将3个表合并在一起的子查询(我不是SQL专家,但我想结果将没有聚集索引!)
foz1284

36

除了order by在您的查询中似乎没有意义的事实之外。要在子选择中使用order by,您将需要使用TOP 2147483647。

SELECT (
  SELECT TOP 2147483647
  COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
  GROUP BY refKlinik_id
  ORDER BY refKlinik_id
) as dorduncuay

我的理解是,从SQL 2005开始,“ TOP 100 PERCENT”不再保证订购:

在SQL Server 2005中,视图定义中的ORDER BY子句仅用于确定TOP子句返回的行。查询视图时,ORDER BY子句不保证结果有序,除非在查询本身中也指定了ORDER BY。

查看SQL Server 2005重大更改

希望这会有所帮助,帕特里克


前100%不保证订购。谢谢这解决了我的问题!
Matt Klepeis'2

27

如果您使用的是SQL Server 2012或更高版本,现在可以轻松解决。添加一个offset 0 rows

SELECT (
  SELECT
  COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
  GROUP BY refKlinik_id
  ORDER BY refKlinik_id OFFSET 0 ROWS
) as dorduncuay

1
在过去20分钟内寻找的所有答案中,这是唯一解决我的问题的答案。
iminiki

我回避这个答案,因为它看起来是如此多余和毫无意义,肯定会有更好的方法使它起作用!就是这样,这就是答案。多么奇怪的功能。
何塞五世

我在SQL Server的CTE(临时命名结果集)上添加了使用ORDER BY的示例,以回答此处的
Jose V

4

您不需要在子查询中排序。将其移到主查询中,并在子查询中包括要排序的列。

但是,您的查询只是返回一个计数,因此我看不到订单要点。


4

如果要构建临时表,请将ORDER BY子句从临时表代码块的内部移至外部。

不允许:

SELECT * FROM (
SELECT A FROM Y
ORDER BY Y.A
) X;

允许:

SELECT * FROM (
SELECT A FROM Y
) X
ORDER BY X.A;

3

将Top命令添加到您的子查询中...

SELECT 
(
SELECT TOP 100 PERCENT 
    COUNT(1) 
FROM 
    Seanslar 
WHERE 
    MONTH(tarihi) = 4
GROUP BY 
    refKlinik_id
ORDER BY 
    refKlinik_id
) as dorduncuay

:)


3

也许这个技巧将帮助某人

SELECT
    [id],
    [code],
    [created_at]                          
FROM
    ( SELECT
        [id],
        [code],
        [created_at],
        (ROW_NUMBER() OVER (
    ORDER BY
        created_at DESC)) AS Row                                 
    FROM
        [Code_tbl]                                 
    WHERE
        [created_at] BETWEEN '2009-11-17 00:00:01' AND '2010-11-17 23:59:59'                                  
        )  Rows                          
WHERE
    Row BETWEEN 10 AND    20;

这里是由字段created_at排序的内部子查询(可以是表中的任何子查询)


2

在此示例中,排序不添加任何信息-集合的COUNT与其所处的顺序相同!

如果您选择的东西确实取决于顺序,则需要执行错误消息告诉您的其中一项操作-使用TOP或FOR XML


2

拥有子查询(嵌套视图)将返回一个数据集,然后可以在调用查询中对其进行排序。对子查询本身进行排序将与调用查询中的结果顺序没有任何(可靠的)区别。

至于您的SQL本身:a)当您返回单个值时,我认为没有理由下订单。b)我仍然没有理由要求子查询,因为您只返回一个值。

我猜这里有更多信息,您可能想告诉我们,以解决您遇到的问题。


1

尝试将order by子句移到sub select之外,然后在sub select中添加order by字段



SELECT * FROM 

(SELECT COUNT(1) ,refKlinik_id FROM Seanslar WHERE MONTH(tarihi) = 4 GROUP BY refKlinik_id)
as dorduncuay 

ORDER BY refKlinik_id 


1

对我来说,这个解决方案也很好:

SELECT tbl.a, tbl.b
FROM (SELECT TOP (select count(1) FROM yourtable) a,b FROM yourtable order by a) tbl

1

美好的一天

对于某些人来说,子查询中的顺序是有问题的。如果您需要基于某种排序删除某些记录,则必须使用子查询中的排序。喜欢

delete from someTable Where ID in (select top(1) from sometable where condition order by insertionstamp desc)

这样就可以删除最后一个插入表单表。实际有三种删除方法。

但是,在许多情况下都可以使用子查询中的排序。

有关在下面的子查询中使用order by的删除方法的链接

http://web.archive.org/web/20100212155407/http://blogs.msdn.com/sqlcat/archive/2009/05/21/fast-ordered-delete.aspx

我希望这会有所帮助。谢谢大家


0

我使用此代码获得第二名的薪水

我也遇到类似的错误

除非还指定了TOP或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效。

我用来避免错误的前100名

从(选择tbl.Coloumn1,CONVERT(varchar,ROW_NUMBER()OVER(ORDER BY(SELECT 1)))中选择* AS作为行号,从(从Coloumn1 desc的Table1顺序中选择前100个*作为tbl)作为tbl,其中tbl.Rowno = 2


0

对于像OP所示的简单计数,严格不需要Order by。如果他们使用子查询的结果,则可能是。我正在处理类似的问题,并且在以下查询中遇到了相同的错误:

-我希望费用表中的行的updatedate等于最大updatedate:

    SELECT * FROM #Costs Cost
    INNER JOIN
    (
        SELECT Entityname, costtype, MAX(updatedtime) MaxUpdatedTime
        FROM #HoldCosts cost
        GROUP BY Entityname, costtype
        ORDER BY Entityname, costtype  -- *** This causes an error***
    ) CostsMax
        ON  Costs.Entityname = CostsMax.entityname
        AND Costs.Costtype = CostsMax.Costtype
        AND Costs.UpdatedTime = CostsMax.MaxUpdatedtime
    ORDER BY Costs.Entityname, Costs.costtype

-***为此,有几种选择:

-添加一个无关的TOP子句,这似乎有点hack:

    SELECT * FROM #Costs Cost
    INNER JOIN
    (
        SELECT TOP 99.999999 PERCENT Entityname, costtype, MAX(updatedtime) MaxUpdatedTime
        FROM #HoldCosts cost
        GROUP BY Entityname, costtype
        ORDER BY Entityname, costtype  
    ) CostsMax
        ON Costs.Entityname = CostsMax.entityname
        AND Costs.Costtype = CostsMax.Costtype
        AND Costs.UpdatedTime = CostsMax.MaxUpdatedtime
    ORDER BY Costs.Entityname, Costs.costtype

-****创建一个临时表以订购maxCost

    SELECT Entityname, costtype, MAX(updatedtime) MaxUpdatedTime
    INTO #MaxCost
    FROM #HoldCosts cost
    GROUP BY Entityname, costtype
    ORDER BY Entityname, costtype  

    SELECT * FROM #Costs Cost
    INNER JOIN #MaxCost CostsMax
        ON Costs.Entityname = CostsMax.entityname
        AND Costs.Costtype = CostsMax.Costtype
        AND Costs.UpdatedTime = CostsMax.MaxUpdatedtime
    ORDER BY Costs.Entityname, costs.costtype

其他可能的解决方法可能是CTE或表变量。但是每种情况都需要您确定最适合您的方法。我倾向于首先看一下临时表。对我来说,这是明确而直接的。YMMV。


0

当您有UNION时,可能需要订购子查询:

您会生成所有教师和学生的电话簿。

SELECT name, phone FROM teachers
UNION
SELECT name, phone FROM students

您要先显示所有教师,然后再显示所有学生,均按顺序显示。因此,您不能通过应用全局订单。

一种解决方案是包括一个键,以强制进行第一个排序,然后对名称进行排序:

SELECT name, phone, 1 AS orderkey FROM teachers
UNION
SELECT name, phone, 2 AS orderkey FROM students
ORDER BY orderkey, name

我认为它的方法比伪造的偏移子查询结果更清晰。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.