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

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

在我的情况下,空白是 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)是它的每个隔间。

标签: sql mariadb gaps-and-islands


【解决方案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 语法错误。你能想到任何不使用窗口函数的解决方案吗?
猜你喜欢
  • 2015-03-28
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 2020-10-29
  • 1970-01-01
  • 2020-09-17
  • 1970-01-01
相关资源
最近更新 更多