MySQL选择分组整数的范围

时间:2019-02-15 07:41:38

标签: mysql range

我已经在数据库中存储了一些客户端编号,分配的ip,routerIP,VLAN和区域

   No    |       ip         |      router     |   idZone   |   vlan  | 
---------------------------------------------------------------------
   9600  |   10.95.65.100   |   10.10.10.26   |     2      |   105   |
   9601  |   10.95.65.101   |   10.10.10.26   |     2      |   105   |
   9602  |   10.95.65.102   |   10.10.10.27   |     2      |   107   |
  16090  |    10.32.5.90    |   10.10.10.25   |     1      |   103   |
  16091  |    10.32.5.91    |   10.10.10.25   |     1      |   103   |
  16092  |    10.32.5.92    |   10.10.10.25   |     1      |   103   |
  16093  |    10.32.5.93    |   10.10.10.25   |     1      |   103   |
  16095  |    10.32.5.95    |   10.10.10.25   |     1      |   103   |
  20100  |   10.20.10.200   |   10.10.10.32   |     3      |   109   |

我需要提供按路由器,区域和VLAN分组的正在使用的客户端编号,以获取如下信息:

 from  |    to   |     router     |   zone   |  vlan
-----------------------------------------------------
 9600  |   9601  |  10.10.10.26   |     2    |   105   |
 9602  |   9602  |  10.10.10.27   |     2    |   107   |
16090  |  16093  |  10.10.10.25   |     1    |   103   |
16095  |  16095  |  10.10.10.25   |     1    |   103   |
20100  |  20100  |  10.10.10.32   |     3    |   109   |

客户编号是唯一的,现在我的查询是这样的:

SELECT
    MIN( no ) AS start_no,
    MAX( no ) AS end_no,
    router,
    idZone,
    vlan
FROM
    address
GROUP BY
    router,
    idZone,
    vlan 

但是该查询未考虑第一个和最后一个之间的缺失点,例如代替了

 from  |    to   |     router     |   zone   |  vlan
--------------------------------------------------------
16090  |  16093  |  10.10.10.25   |     1    |   103   |
16095  |  16095  |  10.10.10.25   |     1    |   103   |

我会

 from  |    to   |     router     |   zone   |  vlan
-----------------------------------------------------
16090  |  16095  |  10.10.10.25   |     1    |   103   |

这是错误的,因为数据库中不存在记录16094

建议?

谢谢!

3 个答案:

答案 0 :(得分:1)

以下查询应适用于所有情况:

(SELECT
    MIN( no ) AS start_no,
    MAX( no ) AS end_no,
    router,
    idZone,
    vlan
FROM
    address a1
    where exists (SELECT a2.no FROM address a2 WHERE a2.no = a1.no + 1) or
          exists (SELECT a2.no FROM address a2 WHERE a2.no = a1.no - 1)
GROUP BY
    router,
    idZone,
    vlan 
)
union
(select no as_no, no as end_no, router,idzone,vlan
from address a1
where not exists (SELECT a2.no FROM address a2 WHERE a2.no = a1.no + 1) and
      not exists (SELECT a2.no FROM address a2 WHERE a2.no = a1.no - 1)
GROUP BY
    router,
    idZone,
    vlan 
 )
   ORDER BY vlan

DEMO

union之前的查询部分将返回所有具有连续client no的组,而查询的另一部分将返回其他单个组。

答案 1 :(得分:0)

您可以从这里开始:

SELECT no
     , CASE WHEN no = @prev+1 THEN @i:=@i ELSE @i:=@i+1 END i
     , @prev := no
  FROM my_table
     , (SELECT @prev:=null, @i:=0) vars
 ORDER
    BY no;

答案 2 :(得分:-1)

您的查询是正确的,但其中一个枢轴字段中可能存在空白,因此难以分组。例如,group by子句中的数据透视列之一说router可以是“ 10.10.10.25”或“ 10.10.10.25”。因此,请尝试修剪空间。

SELECT
    MIN( no ) AS `from`,
    MAX( no ) AS `to`,
    trim(router) router,
    trim(idZone) zone,
    trim(vlan) vlan
FROM
    address
GROUP BY
    trim(router),
    trim(idZone),
    trim(vlan);