mysql - MySQL在两列序列中查找间隙
问题描述
我已经搜索并尝试在此处修改其他一些答案以获得解决方案,但我无法提出任何可行的方法。
我有一个有两列序列的表。不幸的是,第一列是一个字符串,它表示一个十六进制值,例如 0x0010。第二列是另一个从 0 到 15 的计数器。
我正在寻找每个十六进制空间中从 0x0000 到 0xFFFF 以及从 0-15 的间隙。一些十六进制空格可以完全为空,在这种情况下,查询或过程将报告所有 0-15 都是空白的。
例如,给定:
id hex_counter integer_counter
1 0x0000 0
2 0x0000 1
3 0x0000 5
4 0x0001 10
5 0x0003 7
并且只搜索从 0x0 到 0x3,我希望是这样的:
hex_counter gaps
0x0000 2-4
0x0000 6-15
0x0001 0-9
0x0001 11-15
0x0002 0-15
0x0003 0-6
0x0003 8-15
或同一组中的每个数字在其自己的行中。
我试过把它放在一个存储过程中,如下所示:
CREATE PROCEDURE find_blanks()
BEGIN
DECLARE curr INT UNSIGNED DEFAULT 0;
DECLARE max INT UNSIGNED DEFAULT 65535;
CREATE TEMPORARY TABLE IF NOT EXISTS unused
(
hex_counter VARCHAR(255),
gap VARCHAR(255)
);
WHILE curr < max DO
INSERT INTO unused (hex_counter, gap)
SELECT CONCAT( '0x', LPAD(CONV(curr, 10, 16), 4, '0')), m.missing from (
SELECT CONCAT(z.expected, IF(z.got+1<z.expected, CONCAT('-',z.got+1), '')) AS missing FROM ( SELECT @rownuma:=@rownuma-1 AS expected, IF(@rownuma=int_counter, 16, @rownuma:=int_counter) AS got FROM (SELECT @rownuma:=16) AS a JOIN table WHERE hex_counter = CONCAT( '0x', LPAD(CONV(curr, 10, 16), 4, '0')) ORDER BY int_counter) AS z WHERE z.got >= 0 AND z.got < 16
UNION
SELECT CONCAT(z.expected, IF(z.got-1>z.expected, CONCAT('-',z.got-1), '')) AS missing FROM ( SELECT @rownumb:=@rownumb+1 AS expected, IF(@rownumb=int_counter, 0, @rownumb:=int_counter) AS got FROM (SELECT @rownumb:=0) AS a JOIN table WHERE project = project_in AND hex_counter = CONCAT( '0x', LPAD(CONV(curr, 10, 16), 4, '0')) ORDER BY int_counter) AS z WHERE z.got >= 0 AND z.got < 16) as m;
SET curr = curr + 1;
END WHILE;
DROP TABLE IF EXISTS unused;
SELECT * from unused;
END;
这将返回不正确的信息,例如负数等。我即将在 python 中实现一些东西,它将为每个十六进制值发送一个查询,但这将导致大约 65535 个查询,如果可能的话,我想避免这种情况。
谢谢!
解决方案
仅适用于 8.0 之前的版本...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,hex_counter CHAR(6) NOT NULL
,integer_counter INT NOT NULL
);
INSERT INTO my_table VALUES
(1,'0x0000', 0),
(2,'0x0000', 1),
(3,'0x0000', 5),
(4,'0x0001',10),
(5,'0x0003', 7);
DROP TABLE IF EXISTS ints;
CREATE TABLE ints (i INT NOT NULL PRIMARY KEY);
INSERT INTO ints VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
SELECT hex_counter
, MIN(int_counter) range_start
, MAX(int_counter) range_end
FROM
( SELECT hex_counter
, int_counter
, CASE WHEN @prev=j THEN @k:=@k ELSE @k:=@k+1 END k
, @prev:=j b
FROM
( SELECT UNHEX(HEX('0x0000')+h.i) hex_counter
, (i2.i*10)+i1.i int_counter
, COALESCE(x.integer_counter = (i2.i*10)+i1.i,0) j
FROM ints h
JOIN ints i1
JOIN ints i2
LEFT
JOIN my_table x
ON x.hex_counter = UNHEX(HEX('0x0000')+h.i)
AND x.integer_counter = (i2.i*10)+i1.i
JOIN (SELECT @j:=0) vars
WHERE h.i <=3
AND (i2.i*10)+i1.i <= 15
ORDER
BY hex_counter
, int_counter
) a
JOIN (SELECT @prev:=null,@k:=0) vars
ORDER
BY hex_counter
, int_counter
) n
WHERE b = 0
GROUP
BY hex_counter, k;
+-------------+-------------+-----------+
| hex_counter | range_start | range_end |
+-------------+-------------+-----------+
| 0x0000 | 2 | 4 |
| 0x0000 | 6 | 15 |
| 0x0001 | 0 | 9 |
| 0x0001 | 11 | 15 |
| 0x0002 | 0 | 15 |
| 0x0003 | 0 | 6 |
| 0x0003 | 8 | 15 |
+-------------+-------------+-----------+
推荐阅读
- opengl - 如何检查 OpenGL/EGL 是否在无头服务器上检测到 GPU?
- firebase - Flutter - 如何从 firebase 检索数据并保存在 sharedpreference 中
- php - 通过 jQuery 或 Laravel/PHP 在 localStorage 输入中动态添加和保存
- mergefield - 如果 MERGEFIELD "filename".jpg 无效,则 INCLUDEPICTURE 使用备用 jpg
- python - WinRT Python 模块的内存泄漏
- javascript - 日期格式在 Google 数据洞察中不起作用
- c# - C# 我们在拥有私有变量而不是将它们作为方法参数时是否存在性能问题
- jquery - 如何获取元素数据 JQuery
- c# - 如何从数据库加载 RTF 文本并将其显示在 Datagrid 的数据模板中?WPF C#
- vim - cscope 的 vim 命令不在文件下