MySQL выбрать диапазон сгруппированных целых чисел - PullRequest
0 голосов
/ 15 февраля 2019

Я сохранил в базе данных некоторые номера клиентов, назначенный ip, IP-адрес маршрутизатора, 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 голосов
/ 15 февраля 2019

Следующий запрос должен работать для всех сценариев:

(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, а другая часть запроса вернет другие отдельные группы.

0 голосов
/ 15 февраля 2019

Вы можете начать здесь:

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;
0 голосов
/ 15 февраля 2019

Ваш запрос правильный, но в одном из полей сводки может быть пустое место, что затрудняет группировку.Например, один из столбцов сводки в предложении 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...