在查找与某个项目的一组投票匹配的所有用户时避免四元连接
Avoiding a quad join while finding all users that match a set of votes on an item
假设存在以下 table:
a user
table 和 user_id
一个 item
table 和 item_id
和 vote
table 与 user_id, item_id, value
其中 value
可以是 0 到 3 之间的整数。用户可以对项目进行投票。
我正在寻找一种执行查询的方法,以便我可以找到与具有一组指定项目和相应投票值的输入用户投票相同的所有用户。
例如,假设我使用以下信息向应用服务器发送请求:
user_id: 5
votes: [
{ item_id: 7, vote_value: 0 },
{ item_id: 3, vote_value: 3 },
{ item_id: 5, vote_value: 1 },
{ item_id: 41, vote_value: 3 },
{ item_id: 23, vote_value: 2 }
]
然后我想 return 所有至少分享这些结果的用户(即所有其他用户对项目 7 投了 0 票,对项目 3 投了 3 票,对项目 5 投了 1 票,对项目 41 投了 3 票,对项目 23 投了 2 票)。他们可以在其他项目上有更多的选票和其他选票,但至少那些必须匹配。此外,传入的五个投票项目只是一个示例。数量随意。
到目前为止,我想出的唯一解决方案涉及四元联接,并为每个用户的所有 0 票、所有 1 票、所有 2 票和所有 3 票创建一列,然后 return 将整个数据集发送到应用程序服务器以在那里执行计算以找到匹配项。但我希望有更好、更高效的方法。
一种方法
SELECT user_id
FROM votes
GROUP BY user_id
HAVING MAX(CASE WHEN (item_id, value) = (7, 0) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (3, 3) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (5, 1) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (41, 3) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (23, 2) THEN 1 ELSE 0 END) = 1
HAVING
子句也可以用下面的方式表达
...
HAVING MAX(CASE WHEN (item_id, value) = (7, 0) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (3, 3) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (5, 1) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (41, 3) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (23, 2) THEN 1 ELSE 0 END) = 5
假设存在以下 table:
a user
table 和 user_id
一个 item
table 和 item_id
和 vote
table 与 user_id, item_id, value
其中 value
可以是 0 到 3 之间的整数。用户可以对项目进行投票。
我正在寻找一种执行查询的方法,以便我可以找到与具有一组指定项目和相应投票值的输入用户投票相同的所有用户。
例如,假设我使用以下信息向应用服务器发送请求:
user_id: 5
votes: [
{ item_id: 7, vote_value: 0 },
{ item_id: 3, vote_value: 3 },
{ item_id: 5, vote_value: 1 },
{ item_id: 41, vote_value: 3 },
{ item_id: 23, vote_value: 2 }
]
然后我想 return 所有至少分享这些结果的用户(即所有其他用户对项目 7 投了 0 票,对项目 3 投了 3 票,对项目 5 投了 1 票,对项目 41 投了 3 票,对项目 23 投了 2 票)。他们可以在其他项目上有更多的选票和其他选票,但至少那些必须匹配。此外,传入的五个投票项目只是一个示例。数量随意。
到目前为止,我想出的唯一解决方案涉及四元联接,并为每个用户的所有 0 票、所有 1 票、所有 2 票和所有 3 票创建一列,然后 return 将整个数据集发送到应用程序服务器以在那里执行计算以找到匹配项。但我希望有更好、更高效的方法。
一种方法
SELECT user_id
FROM votes
GROUP BY user_id
HAVING MAX(CASE WHEN (item_id, value) = (7, 0) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (3, 3) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (5, 1) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (41, 3) THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN (item_id, value) = (23, 2) THEN 1 ELSE 0 END) = 1
HAVING
子句也可以用下面的方式表达
...
HAVING MAX(CASE WHEN (item_id, value) = (7, 0) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (3, 3) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (5, 1) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (41, 3) THEN 1 ELSE 0 END)
+ MAX(CASE WHEN (item_id, value) = (23, 2) THEN 1 ELSE 0 END) = 5