今天我的SQl问题是如何根据用户配额限制一些查询结果。
这是用例:
用户
+-----+------------+
| 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进行扫描的网页网址列表。
通过这个简单的查询,我可以获得所有页面:
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;
但是一旦我想根据用户scan_quota限制结果,我就会迷失,因为全局LIMIT不会实现我想要的,我不知道如何使用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 :(得分: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