我有一个字段:ages pg_catalog.int4range[][][]
示例值为 {"[0,6)","[8,10)"}
这意味着 2 个范围 0-6 和 8-10。
如何向 WHERE 子句添加正确的条件以进行检查:
- 9和3拟合示例值
- 9 和 9 不适合(每个范围应该只有一个值)
类似于 WHERE ages <@ ARRAY[9,3]
, WHERE ages <@ ARRAY[9,9]
更新
该逻辑描述了应用 child 年龄规则的契约(Contract)条件。我认为将所有数据保存在一个字段中并避免检查和比较的多个阶段是有吸引力的 - 只是为了交叉值和范围。
范围的数量通常是可变的,可以是 1、2、3、4 等。检查的值被计算并仅应用于匹配的范围数量 - 如果 3 个年龄,则只有内部具有 3 个范围的数组。
最佳答案
阐明问题
你的问题显示一个一维数组。所以使用适当的列定义:
ages int4range[]
除了令人困惑之外,它没有任何区别。我引用章节Declaration of Array Types来自手册:
The current implementation does not enforce the declared number of dimensions either. Arrays of a particular element type are all considered to be of the same type, regardless of size or number of dimensions. So, declaring the array size or number of dimensions in
CREATE TABLE
is simply documentation; it does not affect run-time behavior.
此外,问题本身是模棱两可的。例如:
INSERT INTO tbl(ages) VALUES ('{"[0,6)","[5,9)","[8,10)"}')
测试:'{5,8,7}'::int[]
.
如果按顺序应用,检查失败:
5
适合第一个范围 [0,6)
.
8
适合第二个范围 [5,9)
.
7
不适合第三个范围[8,10)
.
但是,应用顺序不同5,7,8
,检查成功。你需要
- 要么保证不重叠的间隔。
- 或按定义的顺序应用检查。
- 阐明两边的元素数量始终匹配。
最后,编辑关于您要对问题执行的操作的解释。不要在评论中隐藏重要信息。
回答
根据评论,假设 1.、2. 和 3. 来自上面的目录。
此查询测试所有 ages
( array of int4range
) 来自 tbl
它们是否适合提供的 age_list
( int[]
):
WITH tbl(id, ages) AS (
VALUES
(1, '{"[0,2)","[4,6)","[8,10)"}'::int4range[])
,(2, '{"[2,4)","[6,8)","[9,10)"}')
) -- stand-in for table
SELECT id, bool_and(i <@ r) AS passes_test
FROM (
SELECT id
,unnest('{1,5,9}'::int[]) AS i -- supply age_list here
,unnest(ages) AS r
FROM tbl
) AS sub
GROUP BY 1
返回:
id | passes_test
----+------------
1 | t
2 | f
要点
CTE
tbl
只是您 table 的替代品。如果tbl
,您可以删除它确实存在。两个
unnest()
函数并排解除两个数组的嵌套。我添加id
(任何唯一列)来标识行。检查每个元素是否包含在
<@
operator 的范围内并重新聚合bool_and
.返回TRUE
当且仅当所有检查都是TRUE
.
关于sql - 检查列表中的每个数字是否与 int4range[] 中的范围匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14665109/