2015-10-08 36 views
1

今天我的SQI问题是如何限制一些基于用户配额的查询结果。如何根据用户配额限制MySQL结果

这里是用例:

  • 用户拥有具有1个... N个网站... N网页
  • 用户有scan_quota这让他(或没有)参观他的网页

用户

+-----+------------+ 
| id | scan_quota | 
+-----+------------+ 
| 1 |   0 | 
| 2 |   10 | 
| 3 |   20 | 
+-----+------------+ 

网站

+-----+---------+------------------------------------------------+ 
| id | user_id | url           | 
+-----+---------+------------------------------------------------+ 
| 1 |  1 | http://www.site1.com       | 
| 2 |  2 | http://www.site2.com       | 
| 3 |  3 | http://www.site3.com       | 
+-----+---------+------------------------------------------------+ 

网页

+-------+------------+--------------------------------------+---------------------+ 
| id | website_id | url         | last_scan_date  | 
+-------+------------+--------------------------------------+---------------------+ 
| 1  |   1 | http://wwww.site1.com/page1   | 2015-07-02 21:00:56 | 
| 2  |   2 | http://wwww.site2.com/page1   | 2015-07-02 21:01:36 | 
| 3  |   3 | http://wwww.site3.com/page1   | 2015-07-02 21:00:32 | 
+-------+------------+--------------------------------------+---------------------+ 
每周我想谁拥有基于用户scan_quota要扫描的网页的URL列表

有了这个简单的查询,我可以得到所有的网页:只要我想根据用户scan_quota我迷路了,因为全局限制不会acheive我想要什么限制结果

SELECT us.id, ws.user_id, wp.id, wp.website_id, wp.url 
FROM users us, webpages wp, websites ws 
    WHERE us.id = ws.user_id 
    AND wp.last_scan_date < '2015-10-08' 
    AND ws.id = wp.website_id 
    ORDER BY wp.website_id ASC; 

但并我不知道如何使用JOIN(INNER或LEFT)来实现我的目标。

我创建了一个SQL Fiddle,可以方便地使用我的用例。

感谢您的建议和帮助!

解决方案不是最优的

在第一查询我提取用户ID和扫描的配额,然后遍历它们来构建我的最终的查询使用UNION ALL(它允许每个用户使用一个LIMIT):

$query .= "(SELECT ws.user_id, wp.id, wp.website_id, wp.url FROM webpages wp, websites ws WHERE ws.user_id = ".$user_id." 
        AND wp.last_scan_date < '2015-10-08' 
        AND ws.id = wp.website_id LIMIT ".$scan_pages.") union all "; 

如果您有办法将这两个查询分组在一个或一个优化的问题中,让我们分享一下。

我也想使用变量和子查询(像我这个例子:https://stackoverflow.com/a/13187418/2295192),但没有运气现在...

+0

见http://stackoverflow.com/questions/2129693/using-limit-within-group-by-to-get-n-results-per-group如何获得每组'N'结果。你的情况唯一的区别是'N'不是一个硬编码的数字,你可以通过加入用户表并使用users.scan_quota来得到它。 – Barmar

回答

5

请使用此查询,你会得到你想要的结果。 您不需要添加您的用户ID。对于每个用户,您可以根据Scan_quota设置限制。

SELECT 
    ws.user_id, 
    wp.id AS webPageID, 
    wp.website_id, 
    @page_counter :=IF (
       (wp.website_id != "") , 
       @page_counter + 1, 
       @page_counter 
       ) AS totalwebpages, 
    wp.url 
FROM 
    (SELECT @page_counter := 0) p, 
    webpages AS wp 
    LEFT JOIN websites AS ws ON ws.id = wp.website_id 
    LEFT JOIN users AS us ON us.id = ws.user_id 
    LEFT JOIN (
    SELECT 
    @limit_scanQuota := @limit_scanQuota +sum(users.scan_quota) as limitScanQuota, 
    users.id 
    FROM 
    (SELECT @limit_scanQuota := 0) s, 
    users 
    GROUP BY 
    users.id 
    ) AS limitQuota ON limitQuota.id = us.id  
WHERE 
    date(wp.last_scan_date) < '2015-10-08' 
    AND @page_counter<limitQuota.limitScanQuota 
GROUP BY 
    wp.id 
ORDER BY 
    wp.id ASC 
+0

感谢您给我一个更合适的查询结构,但我仍然没有看到如何根据扫描配额限制每个用户的结果... – hugsbrugs

+0

您希望根据扫描配额为用户设置限制..您的意思是如果扫描配额为那个用户10,那么你想为该用户设置限制= 10?你想那样吗? –

+0

就是这样!如果用户将扫描配额设置为0,则不应为此用户返回任何结果。如果用户的扫描配额设置为10,但有20个网页,则只能返回10个。 – hugsbrugs