如何在mysql中找到没有间隙的序列号?
考虑一个具有列serialnumber的表productSerialnumber。此列获取产品的单个序列号 产品A的序列号从101到109,然后是111到119和139到150。例如,序列号110和120-138不可用 我想有一个查询或东西,可以返回连续序列号集。 例如,结果将是如何在mysql中找到没有间隙的序列号?,mysql,Mysql,考虑一个具有列serialnumber的表productSerialnumber。此列获取产品的单个序列号 产品A的序列号从101到109,然后是111到119和139到150。例如,序列号110和120-138不可用 我想有一个查询或东西,可以返回连续序列号集。 例如,结果将是 from to ======= ==== 101 109 111 119 139 150 需要考虑的是,这个表有超过一百万行的庞大数据集 任何帮助都会得到
from to
======= ====
101 109
111 119
139 150
需要考虑的是,这个表有超过一百万行的庞大数据集
任何帮助都会得到真正的赏识有更多的发挥:-
SELECT MIN(aFirstSerial), MAX(aLastSerial)
FROM
(
SELECT @FirstSerial:=IF(productSerialnumber = @LastSerial + 1, IF(@FirstSerial = 0, productSerialnumber, @FirstSerial), productSerialnumber) AS aFirstSerial,
@RangeNum:=IF(productSerialnumber = @LastSerial + 1, @RangeNum, @RangeNum + 1) AS aRangeNum,
@LastSerial := productSerialnumber AS aLastSerial
FROM
(
SELECT productSerialnumber
FROM Product
ORDER BY productSerialnumber
) Sub1
CROSS JOIN (SELECT @PrevSerial:=0, @RangeNum:=0, @FirstSerial:=0, @LastSerial:=0) Sub2
) Sub3
GROUP BY aRangeNum
SQL在这里为它摆弄:-
我认为这是非常快的,因为我们避免了连接,只对数据进行一次迭代。唯一的瓶颈是我们使用2个临时表,并且需要使用用户定义的值 无集合语句 With Set语句
SQLFiddle:Minor mod修复meze发现的边缘案例问题+1我尝试了这个,它是迄今为止最快的:-)。测试:您是否尝试了数据集上的查询。有结果吗?
select START_INTERVAL+0, END_INTERVAL+0
from
(
select
if(@start = NULL or @start > PRODUCTSERIALNUMBER, @start='', '') as SET_START,
if (@start = '', @start:= @previous, @start) as START_INTERVAL,
if(PRODUCTSERIALNUMBER - @previous > 1, concat(@end:=@previous,@start:=''), @end:='') as END_INTERVAL,
@previous:= PRODUCTSERIALNUMBER as PRODUCTSERIALNUMBER
from
(
select min(PRODUCTSERIALNUMBER)-2 as PRODUCTSERIALNUMBER from Product
UNION
(select PRODUCTSERIALNUMBER as PRODUCTSERIALNUMBER from Product ORDER BY productSerialnumber)
UNION
select max(PRODUCTSERIALNUMBER)+2 as PRODUCTSERIALNUMBER from Product
) as TEMP
)
as RESULTS where
not START_INTERVAL is null AND
not END_INTERVAL is null AND
not END_INTERVAL = '' AND
not START_INTERVAL - END_INTERVAL > 0;
set @start='';
select select START_INTERVAL+0, END_INTERVAL+0
from
(
select
if (@start = '', @start:= @previous, @start) as START_INTERVAL,
if(PRODUCTSERIALNUMBER - @previous > 1, concat(@end:=@previous,@start:=''), @end:='') as END_INTERVAL,
@previous:= PRODUCTSERIALNUMBER as PRODUCTSERIALNUMBER
from
(
select min(PRODUCTSERIALNUMBER)-2 as PRODUCTSERIALNUMBER from Product
UNION
(select PRODUCTSERIALNUMBER as PRODUCTSERIALNUMBER from Product ORDER BY productSerialnumber)
UNION
select max(PRODUCTSERIALNUMBER)+2 as PRODUCTSERIALNUMBER from Product
) as TEMP
)
as RESULTS where
not RESULTS.START_INTERVAL is null AND
not RESULTS.END_INTERVAL is null AND
not RESULTS.END_INTERVAL = '' AND
not RESULTS.START_INTERVAL - RESULTS.END_INTERVAL > 0;