在Postgres查询中保留数组成员顺序

时间:2018-01-22 06:09:38

标签: sql arrays postgresql postgresql-9.6

我想知道在Postgres中发出select查询时如何保留/利用数组元素的顺序。 (如果相关,则数组是多维的。)

例如,给出以下数据:

 id |             points
----+---------------------------------
  1 | {{1,3},{7,11},{99,101},{0,1}}
  2 | {{99,101},{7,11},{0,1},{77,22}}

我想知道如何编写一个查找points

行的查询
  • 包含子阵列{{7, 11}, {99, 101}}
  • {{99, 101},{7, 11}}

我尝试过使用各种数组运算符(@>&&),使用intarray模块添加索引等,但没有找到可行的解决方案。

1 个答案:

答案 0 :(得分:1)

能够通过1维排除"排除数组"并使用in comarison的结果集,使用Pavel Stěhule建议的function

t=# with c(i,p) as (values(1,'{{1,3},{7,11},{99,101},{0,1}}'::int[][]),(2,'{{99,101},{7,11},{0,1},{77,22}}'))
, p as (select *,a,case when e = '{7, 11}' and lead(e) over (partition by i order by o) = '{99, 101}' and o = lead(o) over (partition by i order by o) -1 then true end from c, reduce_dim(p) with ordinality as a (e,o))
select * from p;
 i |                p                |    e     | o |       a        | case
---+---------------------------------+----------+---+----------------+------
 1 | {{1,3},{7,11},{99,101},{0,1}}   | {1,3}    | 1 | ("{1,3}",1)    |
 1 | {{1,3},{7,11},{99,101},{0,1}}   | {7,11}   | 2 | ("{7,11}",2)   | t
 1 | {{1,3},{7,11},{99,101},{0,1}}   | {99,101} | 3 | ("{99,101}",3) |
 1 | {{1,3},{7,11},{99,101},{0,1}}   | {0,1}    | 4 | ("{0,1}",4)    |
 2 | {{99,101},{7,11},{0,1},{77,22}} | {99,101} | 1 | ("{99,101}",1) |
 2 | {{99,101},{7,11},{0,1},{77,22}} | {7,11}   | 2 | ("{7,11}",2)   |
 2 | {{99,101},{7,11},{0,1},{77,22}} | {0,1}    | 3 | ("{0,1}",3)    |
 2 | {{99,101},{7,11},{0,1},{77,22}} | {77,22}  | 4 | ("{77,22}",4)  |
(8 rows)

现在,你看到逻辑,完成where

t=# with c(i,p) as (values(1,'{{1,3},{7,11},{99,101},{0,1}}'::int[][]),(2,'{{99,101},{7,11},{0,1},{77,22}}'))
, p as (select *,a,case when e = '{7, 11}' and lead(e) over (partition by i order by o) = '{99, 101}' and o = lead(o) over (partition by i order by o) -1 then true end from c, reduce_dim(p) with ordinality as a (e,o))
select i,p from p where "case";
 i |               p
---+-------------------------------
 1 | {{1,3},{7,11},{99,101},{0,1}}
(1 row)

更不用说在顺序数组对的情况下,您可以将它转换为文本并使用like运算符:

t=# with c(i,p) as (values(1,'{{1,3},{7,11},{99,101},{0,1}}'::int[][]),(2,'{{99,101},{7,11},{0,1},{77,22}}'))
select * from c where p::text like '%{7,11},{99,101}%';
 i |               p
---+-------------------------------
 1 | {{1,3},{7,11},{99,101},{0,1}}
(1 row)