如何将查询结果限制为精确的组匹配

时间:2011-12-11 22:43:18

标签: mysql query-optimization subquery

我有一张如下表格:

user  | item
-------------
   X  | Apple
   X  | Orange
   X  | Pear
   Y  | Orange
   Y  | Pear
   Z  | Apple
   Z  | Orange

我的目标是有3个搜索选项:ANYALL(至少),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不匹配的项目”?

2 个答案:

答案 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