2013-01-03 31 views
0

您好,我在執行查詢時遇到問題,這些查詢搜索的用戶(來自用戶表)至少有一個來自一個指定的興趣集和一個興趣集從指定位置設置的位置。所以我有這個測試DB:搜索行中其他值集合中的一組值

CREATE TABLE IF NOT EXISTS `interests` (
     `id` int(11) NOT NULL AUTO_INCREMENT, 
     `name` varchar(255) NOT NULL, 
     PRIMARY KEY (`id`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ; 

    -- 
    -- Dumping data for table `interests` 
    -- 

    INSERT INTO `interests` (`id`, `name`) VALUES 
    (1, 'auto'), 
    (2, 'moto'), 
    (3, 'health'), 
    (4, 'garden'), 
    (5, 'house'), 
    (6, 'music'), 
    (7, 'video'), 
    (8, 'games'), 
    (9, 'it'); 

    -- -------------------------------------------------------- 

    -- 
    -- Table structure for table `locations` 
    -- 

    CREATE TABLE IF NOT EXISTS `locations` (
     `id` int(11) NOT NULL AUTO_INCREMENT, 
     `name` varchar(50) NOT NULL, 
     PRIMARY KEY (`id`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ; 

    -- 
    -- Dumping data for table `locations` 
    -- 

    INSERT INTO `locations` (`id`, `name`) VALUES 
    (1, 'engalnd'), 
    (2, 'austia'), 
    (3, 'germany'), 
    (4, 'france'), 
    (5, 'belgium'), 
    (6, 'italy'), 
    (7, 'russia'), 
    (8, 'poland'), 
    (9, 'norway'), 
    (10, 'romania'); 

    -- -------------------------------------------------------- 

    -- 
    -- Table structure for table `users` 
    -- 

    CREATE TABLE IF NOT EXISTS `users` (
     `id` int(11) NOT NULL AUTO_INCREMENT, 
     `email` varchar(255) NOT NULL, 
     PRIMARY KEY (`id`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ; 

    -- 
    -- Dumping data for table `users` 
    -- 

    INSERT INTO `users` (`id`, `email`) VALUES 
    (1, '[email protected]'), 
    (2, '[email protected]'), 
    (3, '[email protected]'), 
    (4, '[email protected]'), 
    (5, '[email protected]'), 
    (6, '[email protected]'), 
    (7, '[email protected]'), 
    (8, '[email protected]'), 
    (9, '[email protected]'), 
    (10, '[email protected]'); 

    -- -------------------------------------------------------- 

    -- 
    -- Table structure for table `users_interests` 
    -- 

    CREATE TABLE IF NOT EXISTS `users_interests` (
     `user_id` int(11) NOT NULL, 
     `interest_id` int(11) NOT NULL, 
     PRIMARY KEY (`user_id`,`interest_id`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

    -- 
    -- Dumping data for table `users_interests` 
    -- 

    INSERT INTO `users_interests` (`user_id`, `interest_id`) VALUES 
    (1, 1), 
    (1, 2), 
    (2, 5), 
    (2, 7), 
    (2, 8), 
    (3, 1), 
    (4, 1), 
    (4, 5), 
    (4, 6), 
    (4, 7), 
    (4, 8), 
    (5, 1), 
    (5, 2), 
    (5, 8), 
    (6, 3), 
    (6, 7), 
    (6, 8), 
    (7, 7), 
    (7, 9), 
    (8, 5); 

    -- -------------------------------------------------------- 

    -- 
    -- Table structure for table `users_locations` 
    -- 

    CREATE TABLE IF NOT EXISTS `users_locations` (
     `user_id` int(11) NOT NULL, 
     `location_id` int(11) NOT NULL, 
     PRIMARY KEY (`user_id`,`location_id`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

    -- 
    -- Dumping data for table `users_locations` 
    -- 

    INSERT INTO `users_locations` (`user_id`, `location_id`) VALUES 
    (2, 5), 
    (2, 7), 
    (2, 8), 
    (3, 1), 
    (4, 1), 
    (4, 5), 
    (4, 6), 
    (4, 7), 
    (4, 8), 
    (5, 1), 
    (5, 2), 
    (5, 8), 
    (6, 3), 
    (6, 7), 
    (6, 8), 
    (7, 7), 
    (7, 9), 
    (8, 5); 

是否有更好的方法來查詢它比這

SELECT email, 
GROUP_CONCAT(DISTINCT ui.interest_id) AS interests, 
GROUP_CONCAT(DISTINCT ul.location_id) AS locations 
FROM `users` u 
LEFT JOIN users_interests ui ON u.id = ui.user_id 
LEFT JOIN users_locations ul ON u.id = ul.user_id 
GROUP BY u.id 
HAVING IF(interests IS NOT NULL , FIND_IN_SET(2, interests) 
OR FIND_IN_SET(3, interests) , 1) 
AND IF(locations IS NOT NULL , FIND_IN_SET(2, locations) 
OR FIND_IN_SET(3, locations) , 1) 

這是我找到了最好的解決方案,但它在500K和1mil的行仍然緩慢關係表(地點和興趣)。特別是當你與一大組值相匹配時(比如說超過50個位置和興趣)。

所以我想實現這個查詢產生的結果,但有點快:

email    interests  locations 

[email protected]  1,2    [BLOB - 0B] 
[email protected]  1,2,8   1,2,8 
[email protected]  3,7,8   3,7,8 
[email protected]  [BLOB - 0B]  [BLOB - 0B] 
[email protected] [BLOB - 0B]  [BLOB - 0B] 

我也想加入針對SELECT UNION表 - 爲配套設置 - 但它更慢。像這樣:

SELECT * 
FROM `users` u 
LEFT JOIN users_interests ui ON u.id = ui.user_id 
LEFT JOIN users_locations ul ON u.id = ul.user_id 

LEFT JOIN (SELECT 2 as interest UNION SELECT 3 as interest) as `is` ON ui.interest_id = is.interest 
LEFT JOIN (SELECT 2 as location UNION SELECT 3 as location) as `ls` ON ul.location_id = ls.location 

WHERE IF(ui.user_id IS NOT NULL, `is`.interest IS NOT NULL,1) AND 
IF(ul.user_id IS NOT NULL, ls.location IS NOT NULL,1) 

GROUP BY u.id 

我正在使用它作爲基本的瞄準系統。 非常感謝,任何建議!謝謝!

回答

1

你有IS是保留字爲MySQL

,也是你的group by可以減緩你的查詢,但我沒有看到任何意義使用group by u.id這裏,因爲u.id已經unique id

look demo

嘗試使用反引號周圍。

SELECT * 
FROM `users` u 
LEFT JOIN users_interests ui ON u.id = ui.user_id 
LEFT JOIN users_locations ul ON u.id = ul.user_id 

LEFT JOIN (SELECT 2 as interest UNION SELECT 3 as interest) as `is` 
    ON ui.interest_id = `is`.interest 
LEFT JOIN (SELECT 2 as location UNION SELECT 3 as location) as `ls` 
    ON ul.location_id = `ls`.location 


WHERE IF(ui.user_id IS NOT NULL, `is`.interest IS NOT NULL,1) 
AND 
IF(ul.user_id IS NOT NULL, `ls`.location IS NOT NULL,1)