postgresql array_agg包含另一个array_agg

kx1ctssn  于 2023-05-28  发布在  PostgreSQL
关注(0)|答案(1)|浏览(229)
t1
id|entity_type
9|3
9|4
9|5
2|3
2|5
           
t2  
id|entity_type
1|3
1|4
1|5
SELECT t1.id, array_agg(t1.entity_type)
    FROM t1
GROUP BY
    t1.id
HAVING ARRAY_AGG(t1.entity_type ORDER BY t1.entity_type) = 
    (SELECT ARRAY_AGG(t2.entity_type ORDER BY t2.entity_type) 
        FROM t2
    WHERE t2.id = 1
    GROUP BY t2.id);

结果:

t1.id = 9|array_agg{3,4,5}

我有两个表t1t2。我想得到t1.id的值,其中t1.entity_type数组等于t2.entity_type数组。
在这种情况下,一切都很好。对于t2.id = 1,我接收t1.id = 9。两者都有相同的entity_type数组:{3,4,5}
现在我想得到t1.id,不仅对于相等的集合,而且对于较小的集合。如果我这样修改t2

t2  
id|entity_type
1|3
1|4

并以这种方式修改查询:

SELECT t1.id, array_agg(t1.entity_type)
    FROM t1
GROUP BY
    t1.id
HAVING ARRAY_AGG(t1.entity_type ORDER BY t1.entity_type) >= /*MODIFICATION*/
    (SELECT ARRAY_AGG(t2.entity_type ORDER BY t2.entity_type) 
        FROM t2
    WHERE t2.id = 1
    GROUP BY t2.id);

我没有收到预期的结果:

t1.id = 1 has {3, 4, 5}     
t2.id = 1 has {3, 4}

t1中 * 包含 * t2中的数组的数组应该符合条件。我希望像第一种情况一样收到结果,但我没有得到行。
有没有这样的方法:ARRAY_AGG是否包含另一个ARRAY_AGG

irlmq6kh

irlmq6kh1#

清理

使用两个不同的array_agg()调用将是低效的。使用相同的(SELECT列表中的ORDER BYHAVING子句):

SELECT id, array_agg(entity_type ORDER BY entity_type) AS arr
FROM   t1
GROUP  BY 1
HAVING array_agg(entity_type ORDER BY entity_type) = (
   SELECT array_agg(entity_type ORDER BY entity_type)
   FROM   t2
   WHERE  id = 1
   -- GROUP  BY id   -- not needed
   );

手册中的语法基础知识。

“contains”运算符**@>**

Nick commented类似,第二个查询将使用“array contains”运算符@>

SELECT id, array_agg(entity_type ORDER BY entity_type) AS arr
FROM   t1
GROUP  BY 1
HAVING array_agg(entity_type ORDER BY entity_type) @> (
   SELECT array_agg(entity_type ORDER BY entity_type)
   FROM   t2
   WHERE  id = 1
   );

但这对于大table来说是非常低效的。

查询速度更快

这个问题可以转换为关系除法的情况。根据您的表定义,还有更有效的技术。我们在这个相关的问题下收集了一整套材料:

SELECT t1.id
FROM   t2
JOIN   t1 USING (entity_type)
WHERE  t2.id = 1
GROUP  BY 1
HAVING count(*) = (SELECT count(*) FROM t2 WHERE id = 1);

你需要两个索引:
首先是t2(id),通常由主键覆盖。
第二:

CREATE INDEX t1_foo_idx ON t1 (entity_type, id);

添加的id列是可选的,以允许仅索引扫描。列的顺序至关重要:

fiddle
老麻雀

相关问题