总和(列)和按日期分组但获取该日期的所有ID?

时间:2013-05-08 21:30:00

标签: sql group-by aggregate-functions postgresql-9.2

我有以下SQL查询:

SELECT date(created_at), sum(duration) as total_duration 
FROM "workouts" WHERE "workouts"."user_id" = 5 AND "workouts"."category" = 'All' 
GROUP BY date(created_at) ORDER BY date(created_at) ASC

但我也想查询锻炼的id,所以我尝试了这个:

SELECT id as id, date(created_at), sum(duration) as total_duration 
FROM "workouts" WHERE "workouts"."user_id" = 5 AND "workouts"."category" = 'All' 
GROUP BY id, date(created_at) ORDER BY date(created_at) ASC

然而,这导致group by date子句不起作用(即不总结特定日期所有锻炼的持续时间)。我认为这是因为对于具有多个记录的日期,您不能拥有一个ID。即使返回的特定记录有多个与之相关的训练,有没有办法返回ID?

例如,如果昨天有人进行了3次训练,每次训练持续时间为40分钟,则查询将返回120分钟(给定日期的持续时间总和),然后还会返回该日期锻炼的每个ID?

或者我不应该在查询本身中这样做,只是在应用程序中执行此操作?

感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

您应该能够使用子查询来获得结果:

SELECT w1.id,
  w2.created_at
  coalesce(w2.total_duration, 0) total_duration
FROM "workouts" w1
INNER JOIN
(
  SELECT date(created_at) created_at, 
    sum(duration) as total_duration 
  FROM "workouts" 
  WHERE "workouts"."user_id" = 5 
    AND "workouts"."category" = 'All' 
  GROUP BY date(created_at)
) w2
  on w1.created_at = w2.created_at
ORDER BY w2.created_at;

如果您想要返回所有ID,即使没有锻炼的人,也可以使用LEFT JOIN。

答案 1 :(得分:1)

MySQL有group_concat(id),但你一般都会问“sql”。

编辑:对于postgresql,我找到了Postgresql GROUP_CONCAT equivalent?

SELECT array_agg(id) as id_array, date(created_at), sum(duration) as total_duration 
FROM "workouts" WHERE "workouts"."user_id" = 5 AND "workouts"."category" = 'All' 
GROUP BY date(created_at) ORDER BY date(created_at) ASC

答案 2 :(得分:1)

您可以使用Windows功能:

SELECT id as id, date(created_at), sum(duration) as total_duration,
       sum(sum(duration)) over (partition by date(created_at)) as DaysTotal
FROM "workouts"
WHERE "workouts"."user_id" = 5 AND "workouts"."category" = 'All' 
GROUP BY id, date(created_at)
ORDER BY date(created_at) ASC

这将添加另一列,即当天的总数。

答案 3 :(得分:0)

尽管@flaschenpost和@Gordon Linoff的回答非常有帮助,但我最终还是需要两个方面的方面。

以下是我的查询结果:

SELECT array_agg(id) OVER (PARTITION BY date(created_at)) as ids, date(created_at), sum(load_volume) OVER (PARTITION BY date(created_at)) as total_load_volume 
FROM "workouts" WHERE "workouts"."user_id" = 5 AND "workouts"."category" = 'All'
GROUP BY date(created_at), id, load_volume ORDER BY date(created_at) ASC;

要获得每个锻炼ID,如果有多次锻炼,在给定日期我需要使用array_agg以及窗口功能。这是输出:

                                  ids           |    date    | total_load_volume 
------------------------------------------------+------------+-------------------
 {30}                                           | 2013-04-20 |               400
 {29}                                           | 2013-04-23 |               400
 {31}                                           | 2013-04-24 |               400
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {33,34,35,36,37,38,41,42,43,44,45,46,47,48,49} | 2013-04-28 |              1732
 {50}                                           | 2013-04-30 |               400
 {51}                                           | 2013-05-07 |               400
(20 rows)