我正在使用SQL Server 2012 我有一条道路清单,每条道路都有一定长度。例如这样的
Road Length
A 18
B 40
C 65
我想将这些道路分为20公里。因此结果表如下所示:
Road From To
A 0 18
B 0 20
B 20 40
C 0 20
C 20 40
C 40 60
C 60 65
我想我必须使用while循环,但是我不知道该如何构造语法。 只有我能使用我的SQL技能的代码是这样的:
DECLARE @t1 TABLE
(
Road VARCHAR(10)
,RoadLength INT
)
INSERT INTO @t1 VALUES ('A', 18)
INSERT INTO @t1 VALUES ('B', 40)
INSERT INTO @t1 VALUES ('C', 65)
;
DECLARE @t2 TABLE
(
Road VARCHAR(10)
,SectionFrom INT
,SectionTo INT
)
;
DECLARE @max AS INT
,@a AS INT
SET @max = (SELECT MAX(RoadLength) FROM @t1);
SET @a = 0;
WHILE @a <= @max
BEGIN
INSERT INTO @t2
SELECT Road
,@a
,@a + 20
FROM @t1
SET @a = @a + 20
END
;
DELETE a
FROM @t2 a
join @t1 b ON a.Road = b.Road
WHERE a.SectionFrom >= b.RoadLength
;
UPDATE a SET SectionTo = b.RoadLength
FROM @t2 a
JOIN @t1 b ON a.Road = b.Road
WHERE a.SectionTo > b.RoadLength
;
SELECT *
FROM @t2
ORDER BY Road, SectionFrom
因此,对于每条道路,插入一段最长的路段,然后删除这些多余的路段,并更新最后一段,该段短于20公里。 结果令人满意,但是,当然,在处理大量数据时,代码很糟糕并且非常慢。
任何建议如何做到这一点? 谢谢!
答案 0 :(得分:0)
日历表在这里确实派上用场。我们可以定义一个表(或CTE),其中包含我们要显示在报告中的所有细分。也就是说,此“日历”表的每一行都将包含起点和终点的距离,从0到20,然后从20到40,再往后。
然后,我们需要做的就是将此日历表加入您的道路表:
WITH roads AS (
SELECT 'A' AS Road, 18 AS Length UNION ALL
SELECT 'B', 40 UNION ALL
SELECT 'C', 65
),
sections AS (
SELECT 0 AS start, 20 AS finish UNION ALL
SELECT 20, 40 UNION ALL
SELECT 40, 60 UNION ALL
SELECT 60, 80 UNION ALL
SELECT 80, 100
)
SELECT
r.Road,
s.start,
CASE WHEN r.Length < s.finish THEN r.Length ELSE s.finish END AS finish
FROM sections s
INNER JOIN roads r
ON s.start < r.Length;
对上述查询的一个评论是,我们使用CASE
表达式来决定要报告的终点距离。这是因为每条道路的最终路段可能与我们用于路段的20的倍数边界不完全一致。因此,我们总是报告道路长度或路段终点的较小。