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 by t1.entity_type) =
(SELECT ARRAY_AGG(t2.entity_type by t2.entity_type)
FROM t2
WHERE t2.id = 1
GROUP BY t2.id);
结果:
t1.id = 9|array_agg{3,4,5}
我有两张表t1
和t2
。我希望获得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 by t1.entity_type) >= /*MODIFICATION*/
(SELECT ARRAY_AGG(t2.entity_type 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}
<{1}}中的包含 t1
中数组的数组应符合条件。我希望在第一种情况下收到结果,但我没有得到任何行
有没有像ARRAY_AGG那样的方法?
答案 0 :(得分:4)
首先,语法错误。我猜你的意思是:
ARRAY_AGG(t1.entity_type ORDER BY t1.entity_type)
接下来,使用array_agg()
的两个不同调用将是低效的。使用相同的ORDER BY
列表和SELECT
子句中的HAVING
:
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
);
@>
与Nick commented一样,您的第二个查询适用于“包含”运算符@>
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
);
但对于大表来说,非常低效。
这是关系划分的情况。根据您的(缺少的)完全表定义,有更有效的技术。我们在这个相关问题下收集了一整套武器库:
假设 (id, entity_type)
在两个表中都是唯一的,对于大表,这应该明显更快,特别是因为它可以使用索引 on t1
(与原始查询相对):
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
上,通常由主键覆盖
第二位t1.entity_type
:
CREATE INDEX t1_foo_idx ON t1 (entity_type, id);
添加的id
列是可选的,以允许仅索引扫描。列的顺序是必不可少的: