如果指定了SELECT DISTINCT,则ORDER BY项必须出现在选择列表中

时间:2008-11-05 16:08:52

标签: sql sql-server tsql

我将选择列表中的列添加到按列表排序,但它仍然给我错误:

如果指定了SELECT DISTINCT,则ORDER BY项必须出现在选择列表中。

这是存储过程:

CREATE PROCEDURE [dbo].[GetRadioServiceCodesINGroup] 
@RadioServiceGroup nvarchar(1000) = NULL
AS
BEGIN
SET NOCOUNT ON;

SELECT DISTINCT rsc.RadioServiceCodeId,
                rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
FROM sbi_l_radioservicecodes rsc
INNER JOIN sbi_l_radioservicecodegroups rscg 
ON rsc.radioservicecodeid = rscg.radioservicecodeid
WHERE rscg.radioservicegroupid IN 
(select val from dbo.fnParseArray(@RadioServiceGroup,','))
OR @RadioServiceGroup IS NULL  
ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService

END

6 个答案:

答案 0 :(得分:54)

试试这个:

ORDER BY 1, 2

OR

ORDER BY rsc.RadioServiceCodeId, rsc.RadioServiceCode + ' - ' + rsc.RadioService

答案 1 :(得分:44)

虽然它们不是同一个东西,但从某种意义上讲,DISTINCT意味着GROUP BY,因为每个DISTINCT都可以使用GROUP BY重写。考虑到这一点,通过不在聚合组中的东西进行排序是没有意义的。

例如,如果您有这样的表:

col1  col2
----  ----
 1     1
 1     2
 2     1
 2     2
 2     3
 3     1

然后尝试像这样查询:

SELECT DISTINCT col1 FROM [table] WHERE col2 > 2 ORDER BY col1, col2

这没有任何意义,因为可能最终会成为每行多个col2值。它应该用于订单?当然,在这个查询中你知道结果不会那样,但数据库服务器不能提前知道。

现在,你的情况有点不同了。您在order by子句中包含了select子句中的所有列,因此乍一看它们都是分组的。但是,其中一些列包含在计算字段中。当您与distinct结合使用时,distinct指令只能 应用于计算的最终结果:它不知道任何有关计算的来源了。

这意味着服务器实际上并不知道它可以依赖这些列。它知道它们已被使用,但它不知道计算操作是否会产生类似于我上面第一个简单示例的效果。

所以现在你需要做一些其他事情告诉服务器列可以用于订购。有几种方法可以做到这一点,但这种方法应该可行:

SELECT rsc.RadioServiceCodeId,
            rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
FROM sbi_l_radioservicecodes rsc
INNER JOIN sbi_l_radioservicecodegroups rscg 
    ON rsc.radioservicecodeid = rscg.radioservicecodeid
WHERE rscg.radioservicegroupid IN 
    (SELECT val FROM dbo.fnParseArray(@RadioServiceGroup,','))
    OR @RadioServiceGroup IS NULL  
GROUP BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService

答案 2 :(得分:10)

尝试以下方法之一:

  1. 使用列别名:

    订购RadioServiceCodeId,RadioService

  2. 使用列位置:

    ORDER BY 1,2

  3. 您只能按实际出现在DISTINCT查询结果中的列进行排序 - 基础数据无法进行排序。

答案 3 :(得分:3)

Distinct和Group By通常做同样的事情,出于不同的目的......他们都根据被分组的列(或在Select Distinct子句中选择)在内存中创建一个“工作”表 - 和然后在查询读取数据时填充该工作表,仅在值指示需要时才添加新的“行”...

唯一的区别是在Group By中工作表中有任何计算的聚合字段的额外“列”,如Sum(),Count(),Avg()等,需要为每个原始文件更新行读。区别不必这样做...在Group By的特殊情况下,只获得不同的值,(并且输出中没有聚合列),那么它可能是完全相同的查询计划....检查两个选项的查询执行计划并看看它做了什么会很有趣......

当然,如果您正在做的事情(当您的目的是消除重复的行,并且您没有计算任何聚合列),那么可行性是可行的方法

答案 4 :(得分:2)

当您定义连接时,如果要与DISTINCT结合使用,则需要为新列使用ALIAS 一些Ex with sql 2008

--this works 

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName 
    from SalesLT.Customer c 
    order by FullName

--this works too

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) 
    from SalesLT.Customer c 
    order by 1

-- this doesn't 

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName 
    from SalesLT.Customer c 
    order by c.FirstName, c.LastName

-- the problem the DISTINCT needs an order on the new concatenated column, here I order on the singular column
-- this works

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) 
        as FullName, CustomerID 
        from SalesLT.Customer c 

order by 1, CustomerID

-- this doesn't

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName 
     from SalesLT.Customer c 
      order by 1, CustomerID

答案 5 :(得分:0)

您可以尝试子查询:

SELECT DISTINCT TEST.* FROM (
    SELECT rsc.RadioServiceCodeId,
        rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
    FROM sbi_l_radioservicecodes rsc
       INNER JOIN sbi_l_radioservicecodegroups rscg ON  rsc.radioservicecodeid = rscg.radioservicecodeid
    WHERE rscg.radioservicegroupid IN 
       (select val from dbo.fnParseArray(@RadioServiceGroup,','))
        OR @RadioServiceGroup IS NULL  
    ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
) as TEST