PostgreSQL ALL(A) <@ ANY(B)

huangapple go评论73阅读模式
英文:

PostgreSQL ALL(A) <@ ANY(B)

问题

以下是翻译好的内容:

目标是解决以下用例:

  • 表中包含许多 numrange[] 字段。设 A 为其中一个字段。
  • 我们需要根据以下规则请求具有 numrange[] 类型参数 B 的行:ALL(A) <@ ANY(B)

对于表 dt.t 上的 B = {[1,3],[9,10]} 的请求示例如下:

select * from dt.t where ALL(A) <@ ANY(ARRAY[numrange(1,3),numrange(9,10)])

所以这似乎是可行的。但是 ALL 运算符只能用于条件的右侧...
经过一天的尝试,我找不到如何解决这个用例的线索(如果可能的话,不使用函数)。

真正的用例将使用多个字段进行过滤,因此解决方案需要适用于同一 WHERE 子句中的多个字段:

select *
from dt.t
where ALL(A1) <@ ANY(ARRAY[numrange(1,3),numrange(9,10)])
and ALL(A2) <@ ANY(ARRAY[numrange(10,13),numrange(20,20)])

英文:

The objective is to solve the following use case:

  • table contains many numrange[] fields. Let A be one of those fields
  • we need to request rows with a parameter of type numrange[] = B according to this rule : ALL(A) <@ ANY(B)

A sample of a request on table dt.t with B = {[1,3],[9,10]} would be :

select * from dt.t where ALL(A) &lt;@ ANY(ARRAY[numrange(1,3),numrange(9,10)])

So it seems feasible. But the ALL operator can only be used on the right side of the condition...
And turning it around for about a day I don't find a clue on how to solve this use case (not using functions if possible).

The real use case will be using filtering on many fields so the solution needs to be working for multiple fields in the same where clause

select * 
from dt.t 
where ALL(A1) &lt;@ ANY(ARRAY[numrange(1,3),numrange(9,10)]) 
  and ALL(A2) &lt;@ ANY(ARRAY[numrange(10,13),numrange(20,20)])

答案1

得分: 0

以下是翻译好的部分:

找到这个解决方案:

select * 
from dt.t t1 
where (
    select count(1) 
    from (
        select unnest(A) a 
        from dt.t t2 
        where t2.id=t1.id
    ) t 
    where t.a <@ ANY(ARRAY['[1,3)']::numrange])) = array_length(A,1);

这个思路是:

  • 从 dt.t t2 中选择 unnest(A) a,其中 t2.id=t1.id => 给出数组字段 A 的每个元素
  • t.a <@ ANY(ARRAY['[1,3)']::numrange]) => 测试这个元素是否包含在参数中 => <@ ANY(B) 部分
  • (select count(1) [...]) = array_length(A,1) => 检查 A 的所有元素是否有效 => 问题的 ALL(A) 部分

尝试过,有效,看起来合理。唯一真正重要的是 B 是其自身的最小联合(不应存在包含更少 numrange 的 numrange[] 等同于 B 的情况)。
除此之外,似乎可以工作。感谢大家的帮助和时间。

英文:

Found this solution :

select * 
from dt.t t1 
where (
    select count(1) 
    from (
        select unnest(A) a 
        from dt.t t2 
        where t2.id=t1.id
    ) t 
    where t.a &lt;@ ANY(ARRAY[&#39;[1,3)&#39;::numrange])) = array_length(A,1);

The idea is :

  • select unnest(A) a from dt.t t2 where t2.id=t1.id => gives each element of ARRAY field A
  • t.a <@ ANY(ARRAY['[1,3)'::numrange]) => tests if this element is included in the parameter => <@ ANY(B) part
  • (select count(1) [...]) = array_length(A,1) => checks that all elements of A is valid => the ALL(A) part of the problem

Tried it, works, and seems legit. The only thing really important is that B is the minimal union of itself (there shall be no numrange[] equivalent to B with less numrange in it).
Apart from that, seems to work. Thank you all for your help and time.

huangapple
  • 本文由 发表于 2020年1月3日 17:32:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/59576059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定