【问题标题】:How to lookup based on ranged values如何根据范围值查找
【发布时间】:2025-12-02 04:35:01
【问题描述】:

我有一张这样的桌子:

id          name
001to005    ABC
006to210    PQR
211to300    XYZ

这不是最终表,我可以按照我想要的方式制作...所以我想在 id 上查找此数据并提取名称,例如 id 是否在 001-005 范围内然后是 ABC,如果 id 是在 006-010 范围内 .... 然后命名为 XYZ。

我的方法是,将 id 作为正则表达式存储在表中,如下所示:

id                 name
[0][0][1-5]        ABC
[0-2][0-9][0-9]    PQR
[2-3][0-9][0-9]    XYZ

然后查询:

select * from table where '004' ~ id

此查询将返回正确的 ABC,但当范围变大时,我的输入值可能位于第 2 行和第 3 行。 例如:

select * from table where '299' ~ id

此查询将产生 2 行,所以我的问题是使用什么 reg exp 使其更具限制性,或者是否有任何其他方法可以解决此问题:

【问题讨论】:

标签: sql postgresql range


【解决方案1】:

不要存储简单范围的正则表达式,这将非常昂贵并且不能使用索引:表中的每个表达式都必须针对每个查询进行评估以满足条件。 p>

你可以像@a_horse commented 一样使用range types。但是,虽然您不需要添加的 functionality for range types,但这个简单的布局更小更快:

CREATE TABLE tbl (
   id_lo int NOT NULL
 , id_hi int NOT NULL
 , name text NOT NULL
);

INSERT INTO t VALUES
  (  1,   5, 'ABC')
, (  6, 210, 'PQR')
, (211, 300, 'XYZ');

CREATE UNIQUE INDEX foo ON t (id_lo, id_hi DESC);

两个integer占用8个字节,int4range值占用17个字节。大小在表和索引中很重要。

查询:

SELECT * FROM tbl
WHERE  4 BETWEEN id_lo AND id_hi;

下限 (id_lo) 和上限 (id_hi)包含在您的示例数据建议的范围内。
注意范围类型默认排除上限。

还假设前导零无关紧要,因此我们可以使用普通的integer 进行操作。

相关:

在表中强制执行不同的范围:

您仍然不需要表格中的范围类型:

【讨论】: