我有一个users
表,其结构如下:
CREATE TABLE users (
id integer NOT NULL,
email text,
account_id integer,
segment_ids integer[]
);
具有此结构的segments
表:
CREATE TABLE segments (
id integer NOT NULL,
name text
);
我已经构建了一个这样的查询来查找属于段的所有用户:
SELECT * FROM users
WHERE segment_ids @> (
SELECT ARRAY(
SELECT id from segments
WHERE name IN ('Melbourne', 'Male', 'Team #1')
)
)
但是,我不满意使用子查询是实现此目的的最佳方法。是否有更简洁的方式来编写此查询,即使用连接,或者是子查询的方式?
答案 0 :(得分:1)
您可以使用unnest功能执行此操作:
例如,使用上面的表和这些数据:
insert into segments values (1, 'one');
insert into segments values (2, 'two');
insert into segments values (3, 'three');
insert into users values (1, 'email@example.com', 1, array[1,2]);
insert into users values (2, 'email2@example.com', 2, array[2,3]);
运行以下查询:
select u.id, u.email, u.account_id, u.segment_id, s.name from
(select u.id, u.email, u.account_id, unnest(u.segment_ids) segment_id from users u) as u
right join segments s on s.id = u.segment_id
的产率:
1 "email@example.com" 1 1 "one"
1 "email@example.com" 1 2 "two"
2 "email2@example.com" 2 2 "two"
2 "email2@example.com" 2 3 "three"
答案 1 :(得分:1)
如果你真的想要,你可以进行加入。
SELECT DISTINCT users.*
FROM users
JOIN segments
ON ( segments.id = ANY( users.segment_ids ) )
ORDER BY 1;
如果你真的需要查看它匹配的segment_id:
SELECT DISTINCT users.*, array_agg(segments.id) "matched segment id"
FROM users
JOIN segments
ON ( segments.id = ANY( users.segment_ids ) )
GROUP BY users.id, email, account_id, segment_ids
ORDER BY 1;
在您认为合适的地方插入WHERE segments.name IN(...)
信用:@JamesFry用于小提琴中的DDL语句