查找值列表的范围 - sql中的“介于”运算符

Posted

技术标签:

【中文标题】查找值列表的范围 - sql中的“介于”运算符【英文标题】:find the range for list of values - 'between' operator in sql 【发布时间】:2016-12-01 16:27:18 【问题描述】:

我手头有一系列值。我想找出值所在的表中的范围。

值列表(475747003, 476367781, 454313069, 454545398, etc.,) — 1000 个值

DB 表中的范围如下所示:

Start_Range      End_Range
--------------------------
475747000        475747999
476367781        476367782
454313059        454313069

我的输出应该如下所示,即我想找出所有 1000 个值的 Start_RangeEnd_Range。我尝试使用“Between”运算符,但不知道如何将其用于“值列表”?

Start_Range      End_Range
--------------------------
475747000        475747999
476367781        476367782
454313059        454313069

所以基本上,下面的 sql 脚本会抛出错误,

select * from TABLE 
where (475747003, 476367781, 454313069, 454545398) between start_range and end_range;

ORA-01796: 此运算符不能与列表一起使用 01796. 00000 - “此运算符不能与列表一起使用”

所以我想另辟蹊径。

【问题讨论】:

你的值在 x 和 y 之间的带有 MAX() 和 MIN() 或 TOP 1 ORDER BY 和 TOP 1 ORDER BY DESC 的东西会让人想起。 您使用的是哪个 DBMS? 我也看不出这两个例子有什么区别 Oracle 版本 3.2.10.09 数据库表中的 1000 个范围,我想找到值所在的正确范围。但我有一个值列表。不止一个。 【参考方案1】:

您将无法使用“正常”查询来做到这一点(最接近的是用于值列表的 IN 运算符,但您无法测试除相等之外的任何内容)。

如何使用临时表,甚至是“虚拟”表,如下所示:

select myValues.myValue, r.Start_Range, r.End_Range
from (
    select 11111 as MyValue from dual union all
    select 22222 as MyValue from dual union all
    select 33333 as MyValue from dual union all
    ... // all of the values you want to search for
    select 99999 as MyValue from dual
) as myValues
inner join RangesTable r on myValues.myValue between r.Start_Range and r.End_Range

如果你想使用临时表也是一样。您只需将值放入数据库可以视为 set 的内容中,然后加入您的范围。

【讨论】:

当然这可以通过“正常”查询来完成。 IN 不是唯一可用的运算符。 EXISTS 可以与除相等以外的条件一起使用(在这种情况下它可以正常工作)。 只是说您必须将“值列表”转换为基于集合的操作的集合。除此之外,当然,这是正常的。 哦,好吧 - 我以为你的意思是“即使测试值已经在表格中,你也只能使用 IN 并且不能用于范围测试。”如果您的意思是将列表转换为表格,那是另一回事(尽管我使用table(sys.odcinumberlist(..)) 说明的方法也很标准)。【参考方案2】:

在下面的查询中,我模仿了 CTE 中的范围表(不是解决方案的一部分;在您的实际问题中,您只需在主查询中引用您的表),然后输入数字“检查范围”作为动态构建的数字表。您说您只需要显示匹配的范围......在下面的查询中,我显示了每个单独的值及其匹配的范围(如果值不在任何范围内,则显示 NULL)。如果您只需要实际匹配,请将left outer join 更改为inner join。如果您只需要范围,则不要在输出中包含val(在SELECT 子句中)。

with
     ranges_table ( start_range, end_range ) as (
       select 475747000, 475747999 from dual union all
       select 476367781, 476367782 from dual union all 
       select 454313059, 454313069 from dual
     ),
     list_of_values ( val ) as (
       select column_value from table(sys.odcinumberlist
                 (475747003, 476367781, 454313069, 454545398))
     )
select l.val, r.start_range, r.end_range
from   list_of_values l left outer join ranges_table r
                          on l.val between r.start_range and r.end_range
;

VAL        START_RANGE  END_RANGE
---------  -----------  ---------
454313069  454313059    454313069
454545398
475747003  475747000    475747999
476367781  476367781    476367782

如果您只需要 DISTINCT 匹配范围(这比从上表中删除 VAL 列更有意义),您可以改为执行以下操作:

select start_range, end_range
from   ranges_table
where  exists ( select val 
                from   list_of_values 
                where  val between start_range and end_range
              )
;

【讨论】:

以上是关于查找值列表的范围 - sql中的“介于”运算符的主要内容,如果未能解决你的问题,请参考以下文章

SQL学习——BETWEEN运算符

SQL语句怎样查询一个范围

drupal 8 查看日期范围过滤器-“介于”运算符不包括结束日期

T-SQL - 使用按位运算查找缺失值[关闭]

在 Microsoft Access SQL 中使用带数字文本值的 between 运算符

LIKE运算符