假设有一个公司有几个部门。它们中的每一个都分配有一个或几个范围的内部电话号码。分配存储在一个数据库表中,但对于不同的部门以不同的方式存储,如下所示:
dept_name range_start range_end
Sales 10 19
Sales 20 29
HR 30 49
Finance 60 65
Finance 84 93
如何选择相邻范围为联合,以便销售部门。结果中只有一行,如下所示:
dept_name range_start range_end
Sales 10 29
HR 30 49
Finance 60 65
Finance 84 93
答案 0 :(得分:1)
可以通过查找所有范围开始,所有范围结束,然后以正确的顺序将它们连接在一起来完成。
这是一个演示这个概念的SQL小提琴:http://sqlfiddle.com/#!2/6cd35/24
查询...
SELECT oStart.dept_name, oStart.range_start, oEnd.range_end
FROM
(
SELECT strt.dept_name, strt.range_start, @rownum := @rownum + 1 AS rank
FROM
(
SELECT d1.dept_name, d1.range_start, d1.range_end
FROM DepartmentPhoneRanges AS d1
LEFT JOIN DepartmentPhoneRanges AS d2
ON d1.dept_name = d2.dept_name AND d1.range_start = d2.range_end + 1
WHERE d2.dept_name IS NULL
) AS strt
,
(SELECT @rownum := 0) r
ORDER BY dept_name, range_start
) AS oStart
INNER JOIN (
SELECT end.dept_name, end.range_end, @rownum2 := @rownum2 + 1 AS rank2
FROM
(
SELECT d1.dept_name, d1.range_start, d1.range_end
FROM DepartmentPhoneRanges AS d1
LEFT JOIN DepartmentPhoneRanges AS d2
ON d1.dept_name = d2.dept_name AND d1.range_end = d2.range_start - 1
WHERE d2.dept_name IS NULL
) AS end
,
(SELECT @rownum2 := 0) r
ORDER BY dept_name, range_end
) AS oEnd
ON oStart.dept_name = oEnd.dept_name AND oStart.rank = oEnd.rank2
;
注意 - 在mySQL中没有ROW_NUMBER()函数(正如在SQL Server中那样)我在OMG Ponies
'中使用了这个技巧。从this post回答作为替补