4

我有一个字段: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]

更新
逻辑描述了应用儿童年龄规则的合同条件。我认为将所有数据保存在一个字段中并避免多个检查和比较阶段是很有吸引力的 - 只是为了使值和范围相交。
范围数通常是可变的,可以是 1、2、3、4 等。检查的值被计数并仅应用于匹配的范围数 - 如果 3 个年龄,则只有内部具有 3 个范围的数组。

4

1 回答 1

3

澄清问题

你的问题显示一个一维数组。所以使用正确的列定义:

ages int4range[]

除了令人困惑之外,这并不是说它有任何区别。我引用手册中的数组类型声明一章:

当前的实现也不强制声明的维数。无论大小或维数如何,特定元素类型的数组都被认为是同一类型。因此,在其中声明数组大小或维数 CREATE TABLE只是文档;它不会影响运行时行为。

此外,这个问题本身是模棱两可的。前任。:

INSERT INTO tbl(ages) VALUES ('{"[0,6)","[5,9)","[8,10)"}')

测试:'{5,8,7}'::int[]

如果按顺序应用,则检查失败
5适合 1st range [0,6)
8适合第二个范围[5,9)
7不适合第三个范围[8,10)

但是,以不同的顺序应用5,7,8,检查成功。你需要

  1. 要么保证不重叠的间隔。
  2. 或按定义的顺序应用检查。
  3. 澄清两边的元素数量总是匹配的。

最后,在问题中编辑有关您尝试做什么的解释。不要在评论中隐藏重要信息。

回答

根据评论,假设上面目录中的 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

要点

  • CTEtbl只是您桌子的替代品。如果tbl确实存在,您可以将其删除。

  • 这两个unnest()函数并排取消嵌套两个数组。我添加id(任何唯一列)来标识行。

  • <@使用运算符检查每个元素是否包含在范围内,然后使用 重新聚合bool_andTRUE当且仅当所有检查都是 时返回TRUE

于 2013-02-02T23:18:15.047 回答