简答 SQL 和 Django
select a.day_hour, count(*) from (select strftime('%Y-%m-%d %H', created) as day_hour,
user_id, count(*) from post_postview
where post_id=1 group by strftime('%Y-%m-%d %H', created), user_id)
a group by a.day_hour
Django 答案
In [140]: rs = PostView.objects.filter(post_id=1).extra(
{'date_hour': u"strftime('%%Y-%%m-%%d %%H', created)"}).order_by('date_hour').values('user_id', 'date_hour').annotate(count=Count('user_id', distinct=True))
In [141]: rs
Out[141]: <QuerySet [{'date_hour': '2021-05-28 10',
'user_id': 2, 'count': 1}, {'date_hour': '2021-05-28 10',
'user_id': 3, 'count': 1}, {'date_hour': '2021-05-28 11',
'user_id': 2, 'count': 1}, {'date_hour': '2021-05-28 11',
'user_id': 3, 'count': 1}]>
In [142]: rs.values('date_hour').distinct()
Out[142]: <QuerySet [{'date_hour': '2021-05-28 10'},
{'date_hour': '2021-05-28 11'}]>
您需要按两次分组。第一次在date_hour 和user_id 上,第二次在date_hour 上的现有结果集上。
长答案:
由于查询分为两个级别(日期级别和唯一用户),因此您需要两个查询。
在第一步中,您将post_hour 创建的帖子分组。没有这个基本的聚合结果将显示错误的值。
db.sqlite3> select strftime('%Y-%m-%d %H', created) as
day_hour, user_id, count(*) from post_postview where
post_id=1 group by strftime('%Y-%m-%d %H', created), user_id
+---------------+---------+----------+
| day_hour | user_id | count(*) |
+---------------+---------+----------+
| 2021-05-28 10 | 2 | 1 |
| 2021-05-28 10 | 3 | 2 |
| 2021-05-28 11 | 2 | 3 |
| 2021-05-28 11 | 3 | 2 |
+---------------+---------+----------+
正如你所看到的相同时间间隔(2021-05-28 10),
有2 行。现在要计算这两行,需要额外的查询。
再次通过day_hour 应用同一组,我们每小时得到结果。
select a.day_hour, count(*) from (select strftime('%Y-%m-%d
%H', created) as day_hour, user_id, count(*) from
post_postview where post_id=1 group by strftime('%Y-%m-%d
%H', created), user_id) a group by a.day_hour;
+---------------+----------+
| day_hour | count(*) |
+---------------+----------+
| 2021-05-28 10 | 2 |
| 2021-05-28 11 | 2 |
+---------------+----------+
这里我使用了 SQLite 特定的strftime,这是重要的部分。
同样的代码被移植到 Django 中
In [145]:
PostView.objects.filter(post_id=1).extra({'date_hour':
u"strftime('%%Y-%%m-%%d %%H',
created)"}).order_by('date_hour').values('user_id',
'date_hour').values('date_hour').distinct()
Out[145]: <QuerySet [{'date_hour': '2021-05-28 10'},
{'date_hour': '2021-05-28 11'}]>
extra 方法让我们注入 SQL 特定的函数,之后的结果遵循一般的 Django order_by 和 distinct。 SQLite 不支持 distinct on。