不确定如何在SQL Server中进行排序

2 人关注

我正试图对一个结果集进行排序,它看起来非常简单,但我遇到了一点麻烦。

一个人可以有多种地址类型,NULL,公民或邮寄。 我希望任何有NULL地址的人都列在最前面,但随后是他们的公民和邮寄地址。

如果你没有 null ,那么他们的公民和/或邮寄地址就排在有 null 的人之后。

我试过按地址排序,只是把所有的 null 's 列在前面,按名字、地址排序,会有部分效果,但不能保证将 null 's 的人放在前面。

以这一组为例

ID  Person      Address
-------------------------
1   Person A    Civic
1   Person A    Mailing
2   Person B    NULL
2   Person B    Civic
2   Person B    Mailing
3   Person C    NULL
3   Person C    Civic
3   Person C    Mailing
ID   Person     Address
-------------------------
2   Person B    NULL
2   Person B    Civic
2   Person B    Mailing
3   Person C    NULL
3   Person C    Civic
3   Person C    Mailing
1   Person A    Civic
1   Person A    Mailing
    
3 个评论
LKHO
也许它是按名字排序的
姓名或身份证。无所谓 @TheGameiswar
@TheGameiswar 它在问题中说明了 ordering by name, address, will work in part 。下次会说得更清楚
sql
sql-server-2008
select
sql-order-by
Jonnny
Jonnny
发布于 2016-10-04
5 个回答
Tim Biegeleisen
Tim Biegeleisen
发布于 2016-10-05
0 人赞同

这个解决方案使用一个子查询,确定每个 ID (人)是否有一个 NULL 值,他的地址。 如果一个人确实有一个 NULL 的值,那么保存的帐目将有一个大于零的总和。 那些至少 一个 NULL 地址的人首先被排序,然后是那些至少没有一个 NULL 的人。 在这之后,结果集按照 ID ,然后是 Address ,正如你可能已经在做的那样。

SELECT t1.*
FROM yourtable
INNER JOIN
    SELECT ID,
           SUM(CASE WHEN Address IS NULL THEN 1 END) AS hasNull
    FROM yourTable
    GROUP BY ID
    ON t1.ID = t2.ID
ORDER BY CASE WHEN t2.hasNull > 0 THEN 0 ELSE 1 END,
         t1.ID,
         t1.Address
    
你是在生产中使用这么多记录吗? 还是你打算离线运行这个查询以获取信息?
它是一个生产服务器。就字段而言,这是一个大的数据集,是一个联盟。查询只返回5千条记录,需要大约4.5秒。排序会使时间翻倍。不过,这个答案很好 :)
聚合可能是一个真正的性能杀手,但我没有看到任何明显的方法来改善它,除了使用一个完全不涉及它的不同方法之外。 连接也可能是一个问题。
Mureinik
Mureinik
发布于 2016-10-05
已采纳
0 人赞同

Tim Biegeleisen在计算where address IS NULL 的记录数量方面有正确的想法。我认为通过使用 sum ,加上windows子句,而不是用子查询来连接它,可以使查询更优雅一些(可能性能更好一些)。

SELECT id, person, address
FROM   (SELECT id, 
               person, 
               address, 
               SUM(CASE WHEN PERSON IS NULL THEN 1 ELSE 0 END) OVER 
                  (PARTITION BY person) AS s
        FROM   addresses) t
ORDER BY s DESC, person ASC, address ASC
    
Unnikrishnan R
Unnikrishnan R
发布于 2016-10-05
0 人赞同

用这个CTE版本试试。

;WITH CTE_1
  AS (SELECT Id, Person, Address, 
               SUM(CASE WHEN PERSON IS NULL THEN 1 ELSE 0 END) OVER 
              (PARTITION BY person) AS RNO
         FROM   addresses) 
  SELECT Id, Person, Address
  FROM CTE_1
  ORDER BY RNO DESC, person ASC, address ASC
    
Serg
Serg
发布于 2016-10-05
0 人赞同
select *
from mytable
order by min(case when Address is null then 0 else 1 end) over (partition by ID), id, Address;

尽管Sql Server不接受WHERE中的窗口函数,但在ORDER BY中是可以的。所以你在这里不需要任何子查询。

很奇怪,你的帖子来到了低质量的队列(看你的代表),更奇怪的是(看我的代表),我会要求你补充细节,因为只有代码的答案在这里是不被接受的。(但是,这是处理这种情况的 公认方式 )。
Serg
谢谢你让我注意到这一点 @Al.G. 希望我添加的一个解释能真正帮助读者。
是的,是 "不能再审查"。还有,"简单 "这个词在我自己的答案中每次都被删除。
Aman Verma
Aman Verma
发布于 2016-10-05
0 人赞同

你也可以试试这个

SELECT *
FROM @tab
ORDER BY Person,
         (CASE