0

我有一张像这样的桌子:

user | area | start | end
 1       1     12     18
 1       1     19     27
 1       1     29     55 
 1       1     80     99

意思是:从“开始”到“结束”时间,一个“用户”出现在一个“区域”,区域可以重叠。

我想要的是得到如下结果:

user | start-end
 1      12-18,19-27,29-55
 1      80-99

这意味着:组合出现时差小于指定值,即(row2.start - row1.end < 10),并且一个结果行代表用户对该区域的一次“访问”。目前我可以通过使用一条sql语句比较同一张表来区分每次访问并获得访问次数。但我无法找到获得上述结果的方法。任何帮助表示赞赏。

解释:前3个出现链接在一起,因为只有一次访问,因为:row2.start-row1.end < 10 and row3.start-row2.end < 10,最后出现的是新访问,因为:80(row4.start) - 55(row3.end) >= 10 。

4

1 回答 1

1

我们需要两个步骤:

1 - 将一行与其前任合并以使开始和结束在同一行中

SELECT
  user, area, start, end, @lastend AS lastend, @lastend:=end AS ignoreme
FROM 
  tablename, 
  (SELECT @lastend:=0) AS init
ORDER BY user, area, start, end;

2 - 使用差异作为分组标准

SELECT
  ...
FROM
  ...
  (SELECT @groupnum:=0) AS groupinit
GROUP BY
  ... ,
  IF(start-lastend>=10,@groupnum:=@groupnum+1,@groupnum)

现在让我们结合起来:

SELECT
  user, area,
  GROUP_CONCAT(CONCAT(start,"-",end)) AS start_end
FROM (
    SELECT
      user, area, start, end, @lastend AS lastend, @lastend:=end AS ignoreme
    FROM 
      tablename, 
      (SELECT @lastend:=0) AS init
    ORDER BY user, area, start, end
 ) AS baseview,
 (SELECT @groupnum:=0) AS groupinit
GROUP BY
  user, area,
  IF(start-lastend>=10,@groupnum:=@groupnum+1,@groupnum)

编辑

修正错别字并验证:SQLfiddle

于 2013-05-31T08:52:22.930 回答