使用SUM的SQL查询问题
我的数据库模式的相关部分如下所示(RubyonRails迁移代码,但应该易于阅读): 我想要一个查询,它返回一个用户列表,用户列表按自某个日期以来收到的性能点数总数排序。请注意,一个“性能点”行不等于一个点,我们需要将“点”相加 到目前为止,我的查询如下所示:使用SUM的SQL查询问题,sql,postgresql,Sql,Postgresql,我的数据库模式的相关部分如下所示(RubyonRails迁移代码,但应该易于阅读): 我想要一个查询,它返回一个用户列表,用户列表按自某个日期以来收到的性能点数总数排序。请注意,一个“性能点”行不等于一个点,我们需要将“点”相加 到目前为止,我的查询如下所示: SELECT u.id, u.slug, SUM(pp.points) AS total FROM users u JOIN performance_points pp ON pp.user_id = u.id JOIN team_mem
SELECT u.id, u.slug, SUM(pp.points) AS total
FROM users u
JOIN performance_points pp ON pp.user_id = u.id
JOIN team_memberships tm ON tm.team_id = pp.team_id AND tm.user_id = pp.user_id
WHERE (pp.date > '2015-08-02 13:57:14.042221')
GROUP BY pp.id, u.id
ORDER BY total DESC
LIMIT 50
前三个结果是:
"id","slug","total"
32369,"andreas-jensen-9de10dec-0f88-427f-b135-62cebea611c8",245
23752,"kenneth-kjaerstad",95
34179,"marius-mork-rydal",93
为了检查结果是否正确,我计算每个用户的分数。然而,第二个似乎是错误的。我使用Kenneth的id运行此查询:
SELECT SUM(performance_points.points)
FROM performance_points
WHERE performance_points.user_id = 23752
AND (date > '2015-08-02 13:57:14.042221')
我得到:84
。查看Kenneth的所有性能点:
SELECT performance_points.points
FROM performance_points
WHERE performance_points.user_id = 23752
AND (date > '2015-08-02 13:57:14.042221')
我们得到:
"points"
-10
1
-2
95
-10+1-2+95实际上是84,所以我不知道第一个查询是怎么回事。为什么总数是95
我正在运行PostgreSQL 9.3.5版请尝试下面的查询,并让我们知道答案(如果可行):
SELECT u.id, u.slug, SUM(pp.points) AS total
FROM users u
INNER JOIN (select user_id,date,team_id, SUM(points) as points from performance_points group by user_id,date,team_id) pp ON pp.user_id = u.id
INNER JOIN (select team_id, user_id from team_memberships group by team_id, user_id) tm ON tm.team_id = pp.team_id AND tm.user_id = pp.user_id
WHERE (pp.date > '2015-08-02 13:57:14.042221')
GROUP BY u.id, u.slug
ORDER BY total DESC
LIMIT 50
;
请尝试下面的查询,并让我们知道答案(如果可行):
SELECT u.id, u.slug, SUM(pp.points) AS total
FROM users u
INNER JOIN (select user_id,date,team_id, SUM(points) as points from performance_points group by user_id,date,team_id) pp ON pp.user_id = u.id
INNER JOIN (select team_id, user_id from team_memberships group by team_id, user_id) tm ON tm.team_id = pp.team_id AND tm.user_id = pp.user_id
WHERE (pp.date > '2015-08-02 13:57:14.042221')
GROUP BY u.id, u.slug
ORDER BY total DESC
LIMIT 50
;
在看不到所有数据的情况下,有点难以猜测,但可能需要一个CTE来预处理性能点:
with pp_totals as (
select user_id, sum (points) as points
from performance_points
where date > '2015-08-02 13:57:14.042221'
group by user_id
)
SELECT
u.id, u.slug, pp.points AS total
FROM
users u
JOIN pp_totals pp ON pp.user_id = u.id
JOIN team_memberships tm ON tm.user_id = u.user_id
ORDER BY pp.points DESC
limit 50
如果这样做不起作用,您能否创建一个SQL FIDLE并将其发布到您的问题中?在没有看到所有数据的情况下,有点难以猜测,但可能需要一个CTE来预处理性能点:
with pp_totals as (
select user_id, sum (points) as points
from performance_points
where date > '2015-08-02 13:57:14.042221'
group by user_id
)
SELECT
u.id, u.slug, pp.points AS total
FROM
users u
JOIN pp_totals pp ON pp.user_id = u.id
JOIN team_memberships tm ON tm.user_id = u.user_id
ORDER BY pp.points DESC
limit 50
如果这样做不行,您能否创建一个SQL FIDLE并将其发布到您的问题中?如果每个用户的
slug
是唯一的:
SELECT u.id, u.slug, SUM(pp.points) AS total
FROM users u
JOIN performance_points pp
ON u.id = pp.user_id
WHERE pp.date > '2015-08-02 13:57:14.042221'
GROUP BY u.id, u.slug
ORDER BY total DESC
LIMIT 50
否则,您不能选择slug
,因为它不是一个分组列,所以每个组中都有多个值。您希望在性能点中按用户id
分组以获得每个用户id
的总数
,然后加入用户
以获得slug
s
SELECT id, slug, total
FROM users
JOIN (
SELECT user_id, SUM(points) AS total
FROM performance_points
WHERE date > '2015-08-02 13:57:14.042221'
GROUP BY user_id) t
ON id = user_id
ORDER BY total DESC
LIMIT 50
(不清楚您为什么加入团队成员。性能点(用户id,团队id)
可能是一个外键,即所有这些对都已经在其中。)如果slug
每个用户都是唯一的:
SELECT u.id, u.slug, SUM(pp.points) AS total
FROM users u
JOIN performance_points pp
ON u.id = pp.user_id
WHERE pp.date > '2015-08-02 13:57:14.042221'
GROUP BY u.id, u.slug
ORDER BY total DESC
LIMIT 50
否则,您不能选择slug
,因为它不是一个分组列,所以每个组中都有多个值。您希望在性能点中按用户id
分组以获得每个用户id
的总数
,然后加入用户
以获得slug
s
SELECT id, slug, total
FROM users
JOIN (
SELECT user_id, SUM(points) AS total
FROM performance_points
WHERE date > '2015-08-02 13:57:14.042221'
GROUP BY user_id) t
ON id = user_id
ORDER BY total DESC
LIMIT 50
(不清楚您为什么加入团队成员。性能点(用户id,团队id)
可能是一个外键,即所有这些对都已经在其中。)我接受了您的查询并添加了一个过滤器,以限制单个用户。您现在应该看到用户kenneth kjaerstad的四行:
SELECT u.id, u.slug, SUM(pp.points) AS total
FROM
users u
JOIN performance_points pp ON pp.user_id = u.id
JOIN team_memberships tm ON tm.team_id = pp.team_id AND tm.user_id = pp.user_id
WHERE pp.date > '2015-08-02 13:57:14.042221' and u.id = 23752
GROUP BY pp.id, u.id
问题是,这类人把所有其他行都推到了这个列表的最下方,而你从来没有看到除了排名第一的那一行之外,他还有三行
原因是您的分组错误,因为您只需要每个用户的总数pp.id
事实上对于结果中的每一行都应该是唯一的,并且在该列上有一个group by是毫无意义的
另外,我要注意的是,您加入团队成员资格
表似乎没有什么目的,除非您需要保证积分表中的每对用户和团队ID都有团队成员资格。以下是修复方法:
SELECT u.id, min(u.slug) as slug, SUM(pp.points) AS total
FROM
users u
JOIN performance_points pp ON pp.user_id = u.id
JOIN team_memberships tm ON tm.team_id = pp.team_id AND tm.user_id = pp.user_id
WHERE pp.date > '2015-08-02 13:57:14.042221'
GROUP BY u.id
ORDER by total desc
这个答案基本上等同于@philipxy和@Hambone的答案。正如您所见,严格来说,不必使用他们选择的某些构造。希望我对出错原因的解释能对您更喜欢的方法有所帮助。我接受了您的查询,并添加了一个过滤器以限制单个用户。您现在应该看到用户kenneth kjaerstad的四行:
SELECT u.id, u.slug, SUM(pp.points) AS total
FROM
users u
JOIN performance_points pp ON pp.user_id = u.id
JOIN team_memberships tm ON tm.team_id = pp.team_id AND tm.user_id = pp.user_id
WHERE pp.date > '2015-08-02 13:57:14.042221' and u.id = 23752
GROUP BY pp.id, u.id
问题是,这类人把所有其他行都推到了这个列表的最下方,而你从来没有看到除了排名第一的那一行之外,他还有三行
原因是您的分组错误,因为您只需要每个用户的总数pp.id
事实上对于结果中的每一行都应该是唯一的,并且在该列上有一个group by是毫无意义的
另外,我要注意的是,您加入团队成员资格
表似乎没有什么目的,除非您需要保证积分表中的每对用户和团队ID都有团队成员资格。以下是修复方法:
SELECT u.id, min(u.slug) as slug, SUM(pp.points) AS total
FROM
users u
JOIN performance_points pp ON pp.user_id = u.id
JOIN team_memberships tm ON tm.team_id = pp.team_id AND tm.user_id = pp.user_id
WHERE pp.date > '2015-08-02 13:57:14.042221'
GROUP BY u.id
ORDER by total desc
这个答案基本上等同于@philipxy和@Hambone的答案。正如您所见,严格来说,不必使用他们选择的某些构造。希望我对出错原因的解释能对您更喜欢的方法有所帮助。我发现查询实际上没有问题,而是数据有问题。有些用户在多个团队中不止一次出现问题。我发现查询实际上没有问题,但数据有问题。有些用户不止一次在多个团队中,并且出现问题。是否所有性能点行都属于同一个团队成员?对于此用户,它们都是,但情况可能并非总是如此。用户可以在多个团队中,并从每个团队中获得分数。只需将原始查询中的select…
替换为select*
并删除groupby
子句,我相信您会发现问题。请将示例输入、输出和所需输出以及表格约束编辑到您的问题中。在帮助中心了解MCVE。你为什么加入团队成员?性能点(用户id、团队id)不是其中的FK吗?是否所有性能点行都属于同一团队成员?对于此用户,它们是,但可能并非总是如此。用户可以在多个团队中,并从每个团队中获得分数。只需将原始查询中的select…
替换为select*
并删除gr