如何使用 SQL 找到具有预定义最小间隙大小的所有“间隙”?

Posted

技术标签:

【中文标题】如何使用 SQL 找到具有预定义最小间隙大小的所有“间隙”?【英文标题】:How do I find all “gaps” with predefined minimal gap size with SQL? 【发布时间】:2020-03-24 18:48:42 【问题描述】:

我阅读了很多关于寻找差距的好答案(here、here、here),但我仍然不知道如何找到具有最小预定义大小的差距。

在我的情况下,空白是 HE 没有名称顺序的条目。

我还需要像示例中那样从表格的开头找到间隙。

任何人都可以提供一个简洁明了的 SQL 语句,可以通过简单的修改来获得预定义的最小间隙大小?

预期输出示例:

+-----------+----+      +----------------+      +----------------+      +----------------+
| name      | HE |      |   GAPS >= 1    |      |   GAPS >= 2    |      |   GAPS >= 3    |
+-----------+----+      +-----------+----+      +-----------+----+      +-----------+----+
|           |  1 |      | name      | HE |      | name      | HE |      | name      | HE |
| JohnDoe01 |  2 |      +-----------+----+      +-----------+----+      +-----------+----+
| JohnDoe02 |  3 |      |           |  1 |      |           |  4 |      |           | 12 |
|           |  4 |      |           |  4 |      |           |  5 |      |           | 13 |
|           |  5 |      |           |  5 |      |           |  9 |      |           | 14 |
| JohnDoe03 |  6 |      |           |  9 |      |           | 10 |      +-----------+----+
| JohnDoe04 |  7 |      |           | 10 |      |           | 12 |
| JohnDoe05 |  8 |      |           | 12 |      |           | 13 |
|           |  9 |      |           | 13 |      |           | 14 |
|           | 10 |      |           | 14 |      +-----------+----+
| JohnDoe06 | 11 |      +-----------+----+
|           | 12 |
|           | 13 |      
|           | 14 |      
| JohnDoe07 | 15 |      
+-----------+----+

【问题讨论】:

。 .如果HE 有差距怎么办? 这是一种没有间隙的约束。表格代表一个柜子,HE(HeightUnit)是它的每个隔间。 【参考方案1】:

您可以识别间隙以及起点和终点。要识别差距,请计算非差距的数量并汇总:

select min(he), max(he), count(*) as size
from (select t.*, count(name) over (order by he) as grp
      from t
     ) t
where name is null
group by grp;

然后您可以使用having 过滤特定大小的间隙,例如2

having count(*) >= 2

例如。

这总结了差距,每行一个。这实际上对我来说似乎比每行单独的一行更有用。

编辑:

如果你真的想要原始行,你可以这样做:

select t.*
from (select t.*,
             max(he) filter (where name is not null) over (order by he) as prev_he,
             min(he) filter (where name is not null) over (order by he desc) as next_he,
             max(he) over () as max_he
      from t
     ) t
where name is null and
      (max(next_he, max_he + 1) - coalesce(prev_he, 0) - 1) >= 2;

编辑二:

在旧版本的 mysql/MariaDB 中,您可以使用变量:

select min(he), max(he), count(*) as size
from (select t.*,
             (@grp := @grp + (name is not null)) as grp
      from (select t.* from t order by he) t cross join
           (select @grp := 0) params
     ) t
where name is null
group by grp;

【讨论】:

谢谢,您的解释帮助很大,我非常喜欢这个解决方案,但我混淆了我们的数据库设置。我们正在使用 mariadb-5.5(它基于 MySQL 5.5),看起来它不支持窗口功能。 """SELECT t.*, COUNT(name) OVER (ORDER BY HE) as grp FROM Table t""" 表示 SQL 语法错误。你能想到任何不使用窗口函数的解决方案吗?

以上是关于如何使用 SQL 找到具有预定义最小间隙大小的所有“间隙”?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 sqlite 表中找到间隙?

FlexBox布局Android。如何消除视图之间的垂直间隙?

为一堆记录选择最小数据

如何使图像可调整大小的裁剪框

用WORD文档时,如何调整字与字之间的间隙大小

查找具有特定属性的所有类