我有一张如下表格:
user | item
-------------
X | Apple
X | Orange
X | Pear
Y | Orange
Y | Pear
Z | Apple
Z | Orange
我的目标是有3个搜索选项:ANY
,ALL
(至少),EXACT
哪里
ANY 会返回至少搜索过一个项目的用户列表,因此搜索“Apple” - ANY会返回X,Z,搜索“Apple,Orange” - 任何人都会返回X,Y,Z
ALL 会返回搜索了所有项目的用户列表,因此搜索“Apple” - ALL将返回X,Z,搜索“Apple,Orange” - ALL将返回X,Z
EXACT 会返回搜索了所有商品且没有其他商品的用户列表,因此搜索“Apple” - EXACT将不会返回任何结果,搜索“Apple,Orange” “ - EXACT将返回Z
我有前两个问题:
ANY
SELECT user FROM users_items WHERE item IN ($item_array);
ALL
SELECT user FROM users_items WHERE item IN ($item_array)
GROUP BY user HAVING COUNT(DISTINCT item) = $item_search_count;
但我无法弄清楚如何进行精确搜索。我能想到的最好的是:
SELECT user FROM users_items WHERE item IN ($item_array) AND
user NOT IN (
SELECT user FROM users_items WHERE item NOT IN ($item_array)
)
GROUP BY user HAVING COUNT(DISTINCT item) = $item_search_count;
这首先不起作用,因为在真实数据集中,用户或项目可能为null但是当我将其更新为:
SELECT user FROM users_items WHERE item IN ($item_array) AND
user NOT IN (
SELECT user FROM users_items WHERE item NOT IN ($item_array)
AND user IS NOT NULL AND item IS NOT NULL
)
GROUP BY user HAVING COUNT(DISTINCT item) = $item_search_count;
这很有效,但查询速度很慢。
有没有更好的方法来查询“匹配set的所有项目,排除与set set不匹配的项目”?
答案 0 :(得分:0)
使用魔术group_concat
功能:
SELECT user
FROM (
SELECT user, group_concat(item) as items
from user_items
group by 1) x
WHERE items = 'Apple,Orange';
注意:您要搜索的项目列表(例如'Apple,Orange'
)必须按字母顺序排列
答案 1 :(得分:0)
以下作品,应解决您的尺码问题。 但它可能很慢,只需用你的真实数据来试试。
Select
User
FROM
users_items
WHERE
User NOT IN
(
SELECT
users.User
FROM
users_items AS users
JOIN
users_items AS users2 ON users.User = users2.User
WHERE
users2.Item NOT IN ('Apple','Orange')
GROUP BY
users.User
)
GROUP BY
User