联合MySQL中不同行的相邻范围

时间:2014-12-03 15:55:10

标签: mysql sql select

假设有一个公司有几个部门。它们中的每一个都分配有一个或几个范围的内部电话号码。分配存储在一个数据库表中,但对于不同的部门以不同的方式存储,如下所示:

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

1 个答案:

答案 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回答作为替补