我正在使用SQL Server 2008.我在查询中返回了这些数据,看起来非常像Day和ManualOrder订购的那样......
ID Day ManualOrder Lat Lon
1 Mon 0 36.55 36.55
5 Mon 1 55.55 54.44
3 Mon 2 44.33 44.30
10 Mon 3 36.55 36.55
11 Mon 4 36.55 36.55
6 Mon 5 20.22 22.11
9 Mon 6 55.55 54.44
10 Mon 7 88.99 11.22
77 Sun 0 23.33 11.11
77 Sun 1 23.33 11.11
我想要做的是按天订购这些数据,然后是ManualOrder ...但我想要一个行计数器(我们称之为MapPinNumber)。问题是我希望这个行计数器在同一天遇到相同的Lat / Lon时再次重复。然后,如果它是不同的纬度/经度,它可以继续下一行的下一行计数器。我们必须在最终结果中维护Day,ManualOrder。
我将在地图上绘制这些数字,这个数字应代表我将以ManualOrder顺序绘制的引脚编号。该数据代表驾驶员的路线,并且他可以在他的日程表中白天多次去同一个纬度/经度。例如,他开车去沃尔玛,然后是CVS,然后又回到沃尔玛,然后再去沃尔格林。我需要的MapPinNumber列应该是1,2,1,3。由于他周一多次去沃尔玛,但这也是他开车的第一个地方,它总是在地图上的Pin#1。
这就是我需要的结果,我需要计算的MapPinNumber列。我已经尝试过ROW_NUMBER和RANK所能想到的一切,并且疯了!我试图避免使用丑陋的CURSOR。
ID Day ManualOrder Lat Lon MapPinNumber
1 Mon 0 36.55 36.55 1
5 Mon 1 55.55 54.44 2
3 Mon 2 44.33 44.30 3
10 Mon 3 36.55 36.55 1
11 Mon 4 36.55 36.55 1
6 Mon 5 20.22 22.11 4
9 Mon 6 55.55 54.44 2
10 Mon 7 88.99 11.22 5
77 Sun 0 23.33 11.11 1
77 Sun 1 23.33 11.11 1
答案 0 :(得分:4)
以下是我尝试使用ROW_NUMBER
:
WITH CteRN AS(
SELECT *,
Rn = ROW_NUMBER() OVER(PARTITION BY Day ORDER BY ManualOrder),
Grp = ROW_NUMBER() OVER(PARTITION BY Day, Lat, Lon ORDER BY ManualOrder)
FROM tbl
),
CteBase AS(
SELECT *,
N = ROW_NUMBER() OVER(PARTITION BY Day ORDER BY ManualOrder)
FROM CteRN
WHERE Grp = 1
)
SELECT
r.ID, r.Day, r.ManualOrder, r.Lat, r.Lon,
MapPinNumber = ISNULL(b.N, r.RN)
FROM CteRN r
LEFT JOIN CteBase b
ON b.Day = r.Day
AND b.Lat = r.Lat
AND b.Lon = r.Lon
ORDER BY
r.Day, r.ManualOrder
答案 1 :(得分:2)
这可能不是最优雅的解决方案,但它有效:
Select a.*, b.MapPinOrder from MyTable a
left join
(
select distinct Day, Lat, Lon
, row_number()
over (partition by Day order by min(ManualOrder)) as MapPinOrder
from MyTable
group by Day, Lat, Lon
) b
on a.day = b.day
and a.lat = b.lat
and a.lon = b.lon
使用您想要的顺序分别计算行,然后将它们重新连接到完整表。
答案 2 :(得分:2)
您可以将汇总功能MIN
与OVER
一起使用来创建您的排名组,DENSE_RANK
就像这样在其上工作。
简要说明
MIN(ManualOrder)OVER(PARTITION BY Day,Lat,Lon)
获得ManualOrder
,Day
和Lat
组合的最低Lon
。
DENSE_RANK()
只需将此值设置为1
的增量值。
<强> SQL Fiddle 强>
示例数据
CREATE TABLE Tbl ([ID] int, [Day] varchar(3), [ManualOrder] int, [Lat] int, [Lon] int);
INSERT INTO Tbl ([ID], [Day], [ManualOrder], [Lat], [Lon])
VALUES
(1, 'Mon', 0, 36.55, 36.55),
(5, 'Mon', 1, 55.55, 54.44),
(3, 'Mon', 2, 44.33, 44.30),
(10, 'Mon', 3, 36.55, 36.55),
(11, 'Mon', 4, 36.55, 36.55),
(6, 'Mon', 5, 20.22, 22.11),
(9, 'Mon', 6, 55.55, 54.44),
(10, 'Mon', 7, 88.99, 11.22),
(77, 'Sun', 0, 23.33, 11.11),
(77, 'Sun', 1, 23.33, 11.11);
<强>查询强>
;WITH CTE AS
(
SELECT *,GRP = MIN(ManualOrder)OVER(PARTITION BY Day,Lat,Lon) FROM Tbl
)
SELECT ID,Day,ManualOrder,Lat,Lon,DENSE_RANK()OVER(PARTITION BY Day ORDER BY GRP) AS RN
FROM CTE
ORDER BY Day,ManualOrder
<强>输出强>
ID Day ManualOrder Lat Lon RN
1 Mon 0 36.55 36.55 1
5 Mon 1 55.55 54.44 2
3 Mon 2 44.33 44.30 3
10 Mon 3 36.55 36.55 1
11 Mon 4 36.55 36.55 1
6 Mon 5 20.22 22.11 4
9 Mon 6 55.55 54.44 2
10 Mon 7 88.99 11.22 5
77 Sun 0 23.33 11.11 1
77 Sun 1 23.33 11.11 1
答案 3 :(得分:0)
这将为您提供所需的结果。但是,MapPinNumber
可能与您的结果中显示的顺序完全相同。
SELECT *,
MapPinNumber = DENSE_RANK() OVER (PARTITION BY Day ORDER BY Lat, Lon)
FROM Table1
ORDER BY Day, ManualOrder