假设我有下表users
:
id name
1 John
2 Mike
3 Max
表posts
id author_id date title
1 1 2014-12-12 Post 2
2 1 2014-12-10 Post 1
3 2 2014-10-01 Lorem ipsum
...and so on
我想要一个包含以下数据的查询:
用户名
上周内用户的帖子数量
上个月内用户的帖子数量
我只能为每个用户(以下示例中的ID为1)执行此操作:
SELECT
`name`,
(SELECT COUNT(*) FROM `posts`
WHERE
`author` = 1 AND
UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`date`) < 7*24*3600) AS `posts7`,
(SELECT COUNT(*) FROM `posts`
WHERE
`author` = 1 AND
UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`date`) < 30*24*3600) AS `posts30`
FROM `users`
WHERE `id` = 1
我怀疑MySQL允许在一个查询中为所有用户执行此操作,如果我可以在内部和外部SELECT之间交换数据。我可能使用错误的词语,但我真的希望这里的人能理解我的需求,我会得到一些帮助。
答案 0 :(得分:1)
这不是最终的SQL,但会给你一个jist ......
Select name, sum(case when datewithin7 then 1 else 0 end) as posts7,
sum(case when datewithin30 then 1 else 0 end) as posts30
from name
left join posts on name.id = posts.nameid
GROUP BY name.
注意你需要分组。但是我没有时间将案例陈述放在一起......
答案 1 :(得分:1)
尝试这样的事情
SELECT
`name`,
sum(IF(`date` between DATE(NOW()-INTERVAL 7 DAY) and now() , 1, 0) as posts7,
sum(IF(`date` between DATE(NOW()-INTERVAL 30 DAY) and now() , 1, 0) as posts30
FROM
`users` as u, posts as p
WHERE
u.id = p.author_id
GROUP BY
1
答案 2 :(得分:1)
当然,聚合非嵌套查询是解决问题的方法,尽管Benni和xQbert都编写了无限查询 - 这些查询在满足目标的同时非常低效。考虑(根据Benni的回答改编):
SELECT `name`
, SUM(IF(
`date` between DATE(NOW()-INTERVAL 7 DAY) and now()
, 1
, 0) as posts7
, SUM(IF(
p.author_id IS NULL
, 0
, 1) as posts30
FROM `users` as u
LEFT JOIN posts as p
ON u.id = p.author_id
AND p.date > NOW()-INTERVAL 30 DAY
GROUP BY name
请注意,不使用转换为UNIX时间戳允许数据库使用索引(如果可用)来解析查询。
但是,有些情况下使用嵌套查询更有效/更合适。因此,虽然它不是此问题的最佳解决方案:
SELECT
`name`
, (SELECT COUNT(*)
FROM `posts` AS p7
WHERE p7.author = users.id
AND p7.`date` > NOW() - INTERVAL 7 DAY) AS `posts7`
, (SELECT COUNT(*)
FROM `posts` AS p30
WHERE p30.author = users.id
AND p30.`date` > NOW() - INTERVAL 30 DAY) AS `posts30`
FROM `users`
WHERE `id` = 1