在my Drupal website用户可以互相评价,这些带时间戳的评分存储在 pref_rep 表中:
# select id, nice, last_rated from pref_rep where nice=true
order by last_rated desc limit 7;
id | nice | last_rated
------------------------+------+----------------------------
OK152565298368 | t | 2011-07-07 14:26:38.325716
OK452217781481 | t | 2011-07-07 14:26:10.831353
OK524802920494 | t | 2011-07-07 14:25:28.961652
OK348972427664 | t | 2011-07-07 14:25:17.214928
DE11873 | t | 2011-07-07 14:25:05.303104
OK335285460379 | t | 2011-07-07 14:24:39.062652
OK353639875983 | t | 2011-07-07 14:23:33.811986
另外,我将每个用户的性别保留在 pref_users 表中:
# select id, female from pref_users limit 7;
id | female
----------------+--------
OK351636836012 | f
OK366097485338 | f
OK251293359874 | t
OK7848446207 | f
OK335478250992 | t
OK355400714550 | f
OK146955222542 | t
我正在尝试创建2个显示“上个月错过”和“上个月的先生”的Drupal块,但我的问题不是关于Drupal,所以请不要将它移到drupal.stackexchange.com; - )< / p>
我的问题是关于SQL:我怎么能找到最好的用户数 - 以及上个月的用户?我会有两个问题 - 一个是女性,另一个是非女性。
使用PostgreSQL 8.4.8 / CentOS 5.6和SQL有时候很难: - )
谢谢! 亚历
更新
我有一个很好的建议是将时间戳转换为字符串,以便查找上个月的记录(不是过去30天)
UPDATE2:
我最终做了字符串比较:
select r.id,
count(r.id),
u.first_name,
u.avatar,
u.city
from pref_rep r, pref_users u where
r.nice=true and
to_char(current_timestamp - interval '1 month', 'IYYY-MM') =
to_char(r.last_rated, 'IYYY-MM') and
u.female=true and
r.id=u.id
group by r.id , u.first_name, u.avatar, u.city
order by count(r.id) desc
limit 1
答案 0 :(得分:0)
假设您在每月的第一天运行一次,并缓存结果,因为在每个页面上计算投票都是没用的。
首先是一些日期算术:
SELECT now(),
date_trunc( 'month', now() ) - '1 MONTH'::INTERVAL,
date_trunc( 'month', now() );
now | ?column? | date_trunc
-------------------------------+------------------------+------------------------
2011-07-07 16:24:38.765559+02 | 2011-06-01 00:00:00+02 | 2011-07-01 00:00:00+02
好的,我们获得了“上个月”日期时间范围的界限。 现在我们需要一些窗口函数来获得每个性别的第一行:
SELECT * FROM (
SELECT *, rank( ) over (partition by gender order by score desc )
FROM (
SELECT user_id, count(*) AS score FROM pref_rep
WHERE nice=true
AND last_rated >= date_trunc( 'month', now() ) - '1 MONTH'::INTERVAL
AND last_rated < date_trunc( 'month', now() )
GROUP BY user_id) s1
JOIN users USING (user_id)) s2
WHERE rank=1;
请注意,如果出现这种情况,可以为您提供多行。
编辑:
我有一个很好的建议,即将时间戳转换为字符串 查找上个月的记录(不是过去30天)
date_trunc()效果更好。
如果您进行2次查询,则必须两次进行count()。由于用户可能会为其他用户多次投票,因此该表可能会更大,因此扫描一次是件好事。
你不能“将加入回到用户桌面上的查询的外部”,因为你需要性别......
上面的查询大约需要30毫秒,1k用户和10万票,所以你肯定想要缓存它。