我有一个包含最小值和最大值列的表,这些列可能包含重叠数据。
实施例
+--------+--------+
| Minval | Maxval |
+--------+--------+
| 0000 | 1000 |
| 1500 | 8999 |
| 0100 | 0200 |
| 5000 | 6999 |
+--------+--------+
最小值和最大值的可能范围是0000-9999。
我正在寻找一种在数据中找到间隙(孔)的方法。根据上述数据,差距将为1001-1499和9000-9999。
我正在使用php和mysql。
答案 0 :(得分:3)
您不需要PHP代码。您可以在SQL中执行此操作。
差距将从一个以上的最大值开始,并以小于一个小时的一个结束。然后,您只需要查看特定记录是否参与了差距。
select t.*,
t.maxval+1 as gapStart,
(select min(t2.minval) - 1
from t t2
where t2.minval > t.maxval
) as gapEnd
from t
where not exists (select 1
from t t2
where t.maxval + 1 between t2.minval and t2.maxval
)
答案 1 :(得分:1)
MySQL查询可以返回结果,没有脚本。
SELECT CONCAT(LPAD(r.lo,4,'0'),'-',LPAD(r.hi,4,'0')) AS gap
, r.lo
, r.hi
-- , d.minval IS NULL AS gap
-- , d.*
FROM ( SELECT rl.lo, rh.hi
FROM (SELECT 0000 AS lo UNION
SELECT rlo.maxval+1
FROM example1 rlo
WHERE rlo.maxval < 9999
) rl
JOIN (SELECT 9999 AS hi UNION
SELECT rhi.minval-1
FROM example1 rhi
WHERE rhi.minval > 0000
) rh
ON rh.hi >= rl.lo
GROUP BY rl.lo, rh.hi
) r
LEFT
JOIN example1 d
ON r.lo BETWEEN d.minval+0 AND d.maxval+0
OR r.hi BETWEEN d.minval+0 AND d.maxval+0
OR d.minval+0 BETWEEN r.lo AND r.hi
OR d.maxval+0 BETWEEN r.lo AND r.hi
WHERE d.minval IS NULL
ORDER
BY r.lo, r.hi
-- , d.minval, d.maxval
我使用的方法是从一系列可能的差距开始。我们知道每一个潜在的差距都会出现:
0000
或任何maxval+1
9999
或任何minval-1
因此,我们可以生成所有可能的“间隙开始”列表以及所有可能的“间隙结束”列表。 (当我编写查询时,我将这些视为“范围”。我使用别名作为内联视图,r
表示“范围”,rh
表示范围的“高”端,以及rl
表示该范围的“低端”。
分配了别名“r
”的内联视图会返回可能存在间隙的所有可能行。 (它几乎是一个交叉连接,但是我们消除了r.hi小于r.lo的行。我认为用于此的实际术语是“不等式连接”。)
返回到原始范围表的反连接模式消除了不是实际间隙的行,因为与表中的一个范围有一些重叠。 (反连接模式是LEFT JOIN,然后WHERE子句中的谓词消除行是LEFT JOIN操作找到匹配,所以我们留下没有匹配的行。作为替代,相同消除可以使用NOT EXISTS (correlated subquery)
方法完成。)
(当范围表中没有行时,此查询也会返回0000-9999
的差距。)
设置测试用例(我将OP 0000
值调整为0055
,以证明这将确定以0000
开头的差距。)
CREATE TABLE `example1` (minval INT(4), maxval INT(4));
INSERT INTO `example1` VALUES (0055,1000),(1500,8999),(0100,0200),(5000,6999);
gap lo hi
--------- ----- -----
0000-0054 0 54
1001-1499 1001 1499
9000-9999 9000 9999
修改强>
我刚注意到OP注释数据类型为CHAR(4),我认为它是整数类型,可能是INT(4) ZEROFILL
。上面的查询也将工作CHAR类型,但我们需要确保CHAR转换为整数,最简单的方法是在列引用中添加“+ 0”,进行调整并进行测试。
CREATE TABLE `example1` (minval CHAR(4), maxval CHAR(4));
INSERT INTO `example1` VALUES ('0055','1000')
,('1500','8999'),('0100','0200'),('5000','6999');
答案 2 :(得分:0)
您当然需要PHP代码
CREATE TABLE TEMP_TABLE (NUMBER_VALUE INT);
INSERT INTO TEMP_TABLE VALUES (1,2,3,....9999);
你可以用php循环执行此操作或创建一次常量查询并重复使用
然后为主表中的每一行做一个
DELETE FROM TEMP_TABLE WHERE NUMBER_VALUE BETWEEN MINVAL AND MAXVAL;
删除后,您将留下间隙但所有数字。然后你可以遍历这些来存储PHP中的min和max