使用 Postgres 9.4,我有兴趣拥有一个整数数组,例如user_ids_who_like
并提供一个用户数组(例如user_ids_i_am_following
)来对该交集进行排序。
就像是:
select *
from items
where [there is an intersection between
user_ids_who_like with user_ids_i_am_following]
order by intersection(user_ids_who_like).count
Run Code Online (Sandbox Code Playgroud)
是否可以通过数组交集进行分组和排序?
示例数据:
items
name | user_ids_who_like
'birds' | '{1,3,5,8}'
'planes' | '{2,3,4,11}'
'spaceships' | '{3,4,6}'
Run Code Online (Sandbox Code Playgroud)
对于给定的user_ids_who_i_follow = [3,4,11]
,我可以执行以下操作:
select * from items
where <user_ids_who_like intersects with user_ids_who_i_follow>
order by <count of that intersection>
Run Code Online (Sandbox Code Playgroud)
想要的结果:
name | user_ids_who_like | count
'planes' | '{2,3,4,11}' | 3
'spaceships' | '{3,4,6}' | 2
'birds' | '{1,3,5,8}' | 1
Run Code Online (Sandbox Code Playgroud)
一种可能性似乎是这样的:
select id, user_ids_who_like, (user_ids_who_like & '{514, 515}'::int[]) as jt
from queryables
where user_ids_who_like && '{514, 515}'
order by icount(user_ids_who_like & '{514, 515}'::int[]) desc;
Run Code Online (Sandbox Code Playgroud)
但我不知道这种风格(使用 intarray 扩展而不是本机数组函数和运算符)是否已经过时;这里有更老练的用户的任何反馈吗?我不清楚如何使用methods 和 operators做两个数组的交集。
仅使用基本 Postgres 安装工具,您可能会unnest()
计算LATERAL
子查询:
SELECT i.name, i.user_ids_who_like, x.ct
FROM items i
, LATERAL (
SELECT count(*) AS ct
FROM unnest(i.user_ids_who_like) uid
WHERE uid = ANY('{3,4,11}'::int[])
) x
ORDER BY x.ct DESC; -- add PK as tiebreaker for stable sort order
Run Code Online (Sandbox Code Playgroud)
我们不需要 aLEFT JOIN
来保留没有匹配的行,因为count()
总是返回一行 - 0 表示“不匹配”。
intarray
假设integer
阵列而不NULL值或重复时,交叉点算子&
的的intarray
模块将是更简单的:
SELECT name, user_ids_who_like
, array_length(user_ids_who_like & '{3,4,11}', 1) AS ct
FROM items
ORDER BY 3 DESC NULLS LAST;
Run Code Online (Sandbox Code Playgroud)
我NULLS LAST
最后添加了对空数组进行排序 - 在您稍后的问题提醒之后:
在子句中使用重叠运算符&&
WHERE
排除没有任何重叠的行:
SELECT ...
FROM ...
WHERE user_ids_who_like && '{3,4,11}'
ORDER BY ...
Run Code Online (Sandbox Code Playgroud)
为什么?根据文档:
intarray
提供了用于索引支持&&
,@>
,<@
,和@@
运营商,以及规则阵列平等。
以类似的方式应用于标准数组运算符。细节:
或者更激进的是,使用单独的表而不是数组列的规范化模式user_ids_who_like
会占用更多的磁盘空间,但为这些问题提供了带有纯 btree 索引的简单解决方案。
归档时间: |
|
查看次数: |
2405 次 |
最近记录: |