我有一个使用SQL Server 2008的表,它有一个包含两个可排序列的表,一个是手动设置的,另一个是通过系统过程计算的(此过程将整体排序,并从10开始分配排序,直到最高行数乘以10)
ID Manual System
------------------------
1 null 300
2 2 380
3 null 500
4 null 200
我试图让它将id分类为4,2,1,3
我希望输出在应用时对系统进行手动排序。如果添加了另一行并且还需要考虑手动排序,则会使事情进一步复杂化。
ID Manual System
-----------------------
1 null 300
2 2 380
3 null 500
4 null 200
5 5 100
所以新的排序将是4,2,1,3,5
ID Manual System
-----------------------
4 null 200
2 2 380
1 null 300
3 null 200
5 5 100
有什么想法吗?我尝试过Rank,Dense_Rank,Row_Number等。
已经给出的解决方案似乎对我的例子是正确的。我忘了提到第三列personID也是这里的一个因素。
ID Manual System PersonID
-------------------------------------
4 null 200 22
2 2 380 22
1 null 300 22
3 null 200 22
5 5 100 22
8 1 210 25
6 1 480 25
7 null 600 25
9 4 800 25
10 null 990 25
因此,我首先必须按人员订购,然后按手动排序,然后按排序。这似乎仍然给我一个问题。
答案 0 :(得分:3)
我认为这就是你所需要的。这有点难以解释。
Basically inserting not null manual values as row index (or row number) to the record list ordered by system.
;with cte as (
select id, manual,system,
convert(decimal(10,1),row_number() over(order by system)) rn
from t
where manual is null
union all
select id, manual,system, convert(decimal(10,1),manual-0.5) rn
from t
where manual is not null
)
select id,manual,system
from cte
order by rn
| ID | MANUAL | SYSTEM |
------------------------
| 4 | (null) | 200 |
| 2 | 2 | 380 |
| 1 | (null) | 300 |
| 3 | (null) | 500 |
| 5 | 5 | 100 |
答案 1 :(得分:3)
如果我了解您的要求,您希望按System列排序,除非提供了Manual列,并且在这种情况下,请将其用作排序位置?如果是这样,那么这应该适用于CASE
和ROW_NUMBER
:
SELECT Id, Manual, System
FROM (
SELECT Id,
Manual,
System,
ROW_NUMBER() OVER (ORDER BY Manual, System) rn
FROM YourTable) t
ORDER BY CASE WHEN Manual IS NULL THEN RN ELSE Manual END, COALESCE(Manual,RN+1)
答案 2 :(得分:3)
以下是我的解决方案:http://sqlfiddle.com/#!3/a32a0/1/0
SELECT *
FROM
(
SELECT
ID
, ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY System)-.1 AS rn
, Manual
, System
, PersonID
FROM YourTable
) t0
ORDER BY PersonID
, COALESCE(Manual, RN)
以下是解释:
PARTITION BY...
之前ORDER BY...
会重置MANUAL
的每个分组的索引ROW_NUMBER
和MANUAL
排序的自然排序之间存在联系,我会减去.1((0,1)之间的任意数量)。如果出现平局,则优先考虑MANUAL
值ORDER BY
PARTITION BY
值,先确保正确的分组,然后按MANUAL
的第一个非空值进行排序, RN
试一试。 +指向前两个答案的起点。我用其中一个作为起点,并从那里重写。
编辑:删除了.1的减法并添加了一个新的排名函数,它“优化”优化器,使其优先于手动排名。我不知道在所有情况下这是否成立,或者优化器是否会在其他情况下无法按此顺序给出结果,但我想将这些结果包括在内以防它们有用。
我的更新查询如下:
SELECT *
FROM
(
SELECT
ID
, ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY System) AS rn
, ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY Manual) AS rn_throwaway
, Manual
, System
, PersonID
FROM YourTable
) t0
ORDER BY PersonID
, COALESCE(Manual, RN)
正在使用的示例位于http://sqlfiddle.com/#!3/1831d/55/0和http://sqlfiddle.com/#!3/a32a0/9/0