如何对多列进行稳定排序?
How to perform stable sort over multiple columns?
假设我有一个数据集包含:
Date Id
-------------- ----
11/1/2017 null
11/4/2017 3
11/5/2017 null
11/12/2017 10
null 1
null 2
null 7
null 8
null 9
我希望对行进行排序,以便两列都增加。
使用天真的 ORDER BY Date, ID
不会这样做:
有订单
有一个排序满足我想要的排序结果:
- 日期列总是递增
- id 列的值一直在增加
当然,这不是唯一的顺序:
Date Id
-------------- ---------------
null 1
11/1/2017 null
null 2
11/4/2017 3
null 7
null 8
null 9
11/5/2017 null
11/12/2017 10
一种编程语言可以做到
我知道我可以在客户端完成这个。在函数式函数式编程语言中:使用 stable sorting algorithm:
A stable sort is one which preserves the original order of the input
set, where the comparison algorithm does not distinguish between two
or more items.
Consider a sorting algorithm that sorts cards by rank, but not by
suit. The stable sort will guarantee that the original order of cards
having the same rank is preserved; the unstable sort will not.
不幸的是我有
- 910 万行
- 1.8 GB
的单调递增行以尽可能按时间顺序排列。显然我更愿意在服务器上执行此操作 - 这非常适合处理大量数据。
如何在 SQL 服务器中执行稳定排序?
示例数据
CREATE TABLE #SortDemo (Date datetime NULL, Id int NULL)
INSERT INTO #SortDemo (Date, Id)
VALUES
('20171101', null),
('20171104', 3),
('20171105', null),
('20171112', 10),
(null, 1),
(null, 2),
(null, 7),
(null, 8),
(null, 9)
SELECT * FROM #SortDemo
ORDER BY Date, Id
这是一个可以解决的问题。 You不用举手说电脑不能用来解决问题
从数据开始,添加一个新的代理 "Rank" 列。
Date Id Rank
-------------- ---- ----
null 7 null
null 1 null
null 9 null
null 2 null
null 8 null
11/1/2017 null null
11/4/2017 3 null
11/5/2017 null null
11/12/2017 10 null
11/13/2017 null null
然后将 Rank
播种到 Id
:
UPDATE SortDemo SET Rank = Id
WHERE Id IS NOT NULL
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null null
11/4/2017 3 3
11/5/2017 null null
11/12/2017 10 10
11/13/2017 null null
然后对于剩余的带有日期的项目,我们需要将其分配到 "next" 等级:
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null null <-- 3
11/4/2017 3 3
11/5/2017 null null <-- 10
11/12/2017 10 10
11/13/2017 null null <-- ?
和
UPDATE SortDemo SET Rank = (
SELECT MIN(Rank) FROM SortDemo s2
WHERE s2.Date >= SortDemo.Date)
WHERE SortDemo.Date IS NOT NULL
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null 3 <--
11/4/2017 3 3
11/5/2017 null 10 <--
11/12/2017 10 10
11/13/2017 null null <-- ?
也有没有项目的边缘情况 "after" 我们;我们可以通过倒退到前一个最高等级来解决这个问题:
UPDATE SortDemo SET Rank = (
SELECT MAX(Rank) FROM SortDemo s2
WHERE s2.Date <= SortDemo.Date)
WHERE SortDemo.Date IS NOT NULL
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null 3
11/4/2017 3 3
11/5/2017 null 10
11/12/2017 10 10
11/13/2017 null 10 <--10
我们完成了
我们现在可以按代理 Rank
排序,并按 Date
:
排序打破平局
SELECT * FROM SortDemo
ORDER BY Rank, Date
Date Id Rank
-------------- ---- ----
null 1 1
null 2 2
11/1/2017 null 3
11/4/2017 3 3
null 7 7
null 8 8
null 9 9
11/5/2017 null 10
11/12/2017 10 10
11/13/2017 null 10
解决方案完成。 Sql Fiddle
答案保存到周一,所以我可以让人们有机会通过解决独特的问题赢得声誉。
假设我有一个数据集包含:
Date Id
-------------- ----
11/1/2017 null
11/4/2017 3
11/5/2017 null
11/12/2017 10
null 1
null 2
null 7
null 8
null 9
我希望对行进行排序,以便两列都增加。
使用天真的 ORDER BY Date, ID
不会这样做:
有订单
有一个排序满足我想要的排序结果:
- 日期列总是递增
- id 列的值一直在增加
当然,这不是唯一的顺序:
Date Id
-------------- ---------------
null 1
11/1/2017 null
null 2
11/4/2017 3
null 7
null 8
null 9
11/5/2017 null
11/12/2017 10
一种编程语言可以做到
我知道我可以在客户端完成这个。在函数式函数式编程语言中:使用 stable sorting algorithm:
A stable sort is one which preserves the original order of the input set, where the comparison algorithm does not distinguish between two or more items.
Consider a sorting algorithm that sorts cards by rank, but not by suit. The stable sort will guarantee that the original order of cards having the same rank is preserved; the unstable sort will not.
不幸的是我有
- 910 万行
- 1.8 GB
的单调递增行以尽可能按时间顺序排列。显然我更愿意在服务器上执行此操作 - 这非常适合处理大量数据。
如何在 SQL 服务器中执行稳定排序?
示例数据
CREATE TABLE #SortDemo (Date datetime NULL, Id int NULL)
INSERT INTO #SortDemo (Date, Id)
VALUES
('20171101', null),
('20171104', 3),
('20171105', null),
('20171112', 10),
(null, 1),
(null, 2),
(null, 7),
(null, 8),
(null, 9)
SELECT * FROM #SortDemo
ORDER BY Date, Id
这是一个可以解决的问题。 You不用举手说电脑不能用来解决问题
从数据开始,添加一个新的代理 "Rank" 列。
Date Id Rank
-------------- ---- ----
null 7 null
null 1 null
null 9 null
null 2 null
null 8 null
11/1/2017 null null
11/4/2017 3 null
11/5/2017 null null
11/12/2017 10 null
11/13/2017 null null
然后将 Rank
播种到 Id
:
UPDATE SortDemo SET Rank = Id
WHERE Id IS NOT NULL
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null null
11/4/2017 3 3
11/5/2017 null null
11/12/2017 10 10
11/13/2017 null null
然后对于剩余的带有日期的项目,我们需要将其分配到 "next" 等级:
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null null <-- 3
11/4/2017 3 3
11/5/2017 null null <-- 10
11/12/2017 10 10
11/13/2017 null null <-- ?
和
UPDATE SortDemo SET Rank = (
SELECT MIN(Rank) FROM SortDemo s2
WHERE s2.Date >= SortDemo.Date)
WHERE SortDemo.Date IS NOT NULL
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null 3 <--
11/4/2017 3 3
11/5/2017 null 10 <--
11/12/2017 10 10
11/13/2017 null null <-- ?
也有没有项目的边缘情况 "after" 我们;我们可以通过倒退到前一个最高等级来解决这个问题:
UPDATE SortDemo SET Rank = (
SELECT MAX(Rank) FROM SortDemo s2
WHERE s2.Date <= SortDemo.Date)
WHERE SortDemo.Date IS NOT NULL
Date Id Rank
-------------- ---- ----
null 7 7
null 1 1
null 9 9
null 2 2
null 8 8
11/1/2017 null 3
11/4/2017 3 3
11/5/2017 null 10
11/12/2017 10 10
11/13/2017 null 10 <--10
我们完成了
我们现在可以按代理 Rank
排序,并按 Date
:
SELECT * FROM SortDemo
ORDER BY Rank, Date
Date Id Rank
-------------- ---- ----
null 1 1
null 2 2
11/1/2017 null 3
11/4/2017 3 3
null 7 7
null 8 8
null 9 9
11/5/2017 null 10
11/12/2017 10 10
11/13/2017 null 10
解决方案完成。 Sql Fiddle
答案保存到周一,所以我可以让人们有机会通过解决独特的问题赢得声誉。