如果找不到记录,则返回0作为求和结果

6l7fqoea  于 2021-06-17  发布在  Mysql
关注(0)|答案(4)|浏览(343)

我试图总结一个特定用户在过去7天(实际的一天是第7天)每天活动的卡路里。有表user和activities以及Map表user\u activities。
以下示例适用于id=1的用户;
总结过去7天每天的卡路里(这一天是第7天)*/

SELECT  
    DATE(a.end_time), SUM(a.calories)
FROM
    activities a
JOIN
    user_activities uc ON uc.activity_id = a.id
WHERE
    uc.user_id = 1
    AND DATE(a.end_time) >= CURRENT_DATE - INTERVAL 6 DAY
GROUP BY 
    DATE(a.end_time) DESC

该查询返回以下结果集:

2018-12-28   9600
2018-12-27   1200
2018-12-26   1200
2018-12-25   1200
2018-12-24   4800
2018-12-22   1200

这是正确的,但现在我的问题是,正如你在列表中看到的,2018年12月23日没有列出,因为这一天没有活动。现在我要展示

2018-12-23   0

而不是什么都没有。
我怎样才能得到想要的结果?
谢谢你的帮助
我也尝试了ifnull和coalesce,但到目前为止没有运气
总结过去7天每天的卡路里(这一天是第7天)*/

SELECT  
    DATE(a.end_time), SUM(a.calories)
FROM
    activities a
JOIN 
    user_activities uc ON uc.activity_id = a.id
WHERE 
    uc.user_id = 1
    AND DATE(a.end_time) >= CURRENT_DATE - INTERVAL 6 DAY
GROUP BY
    DATE(a.end_time) DESC

结果:

2018-12-28   9600
2018-12-27   1200
2018-12-26   1200
2018-12-25   1200
2018-12-24   4800
2018-12-22   1200

预期结果:

2018-12-28   9600
2018-12-27   1200
2018-12-26   1200
2018-12-25   1200
2018-12-24   4800
2018-12-23      0
2018-12-22   1200
``` `Activities` 表格:
![](https://i.stack.imgur.com/gfrtR.png)
yks3o0rb

yks3o0rb1#

如果你的活动表中没有列出某一天的活动,那么fa06的诀窍就行不通了。一个简单的方法是在求和之前,在上面添加一些零记录:

SELECT DATE(d), SUM(c)
FROM (
  SELECT  a.end_time as d, a.calories as c
  FROM activities a
  JOIN user_activities uc ON uc.activity_id = a.id
  WHERE uc.user_id = 1
  AND DATE(a.end_time) >= CURRENT_DATE - INTERVAL 6 DAY
  UNION ALL
  SELECT CURRENT_DATE, 0
  UNION ALL
  SELECT CURRENT_DATE - INTERVAL 1 DAY, 0
  UNION ALL
  SELECT CURRENT_DATE - INTERVAL 2 DAY, 0
  UNION ALL
  SELECT CURRENT_DATE - INTERVAL 3 DAY, 0
  UNION ALL
  SELECT CURRENT_DATE - INTERVAL 4 DAY, 0
  UNION ALL
  SELECT CURRENT_DATE - INTERVAL 5 DAY, 0
  UNION ALL
  SELECT CURRENT_DATE - INTERVAL 6 DAY, 0
) z
GROUP BY DATE(d)

fa06的方法依赖于activities表中每天有一条记录。这是解决问题的一种有效方法,但您尚未明确这些表包含哪些数据(提示:发布db问题时,请务必包含每个表中的示例数据)
使用这种方法,我们可以正常地进行查找,但我们也会生成7个伪行,其中包含过去7天的日期和0卡路里的计数。加上真正的卡路里,这些是无脂肪的;)当没有某一天的数据时,这些单独提供0
如果需要更多的天数,可以考虑使用行生成模式。mysql不像其他数据库那样有行生成器,但最简单的技巧是创建变量,用0初始化它,然后递增,并在从至少有30行的表返回的每一行上使用它:

SELECT CURRENT_DATE - INTERVAL (@row := @row + 1) DAY as dt, 0 as cal
FROM activities t, (SELECT @row := -1) r
LIMIT 30

这背后的理论是:表至少有30行,@row变量被初始化为-1,并且存在于整个会话范围内用于查询。当行被拉出并返回时,@row被递增然后返回(所以它是0,1,2..)这个递增的计数用来减去当前数据的0,1,2等天,给我们一个过去30天的日期序列

SELECT DATE(d), SUM(c)
FROM (
  SELECT  a.end_time as d, a.calories as c
  FROM activities a
  JOIN user_activities uc ON uc.activity_id = a.id
  WHERE uc.user_id = 1
  AND DATE(a.end_time) >= CURRENT_DATE - INTERVAL 29 DAY
  UNION ALL

  SELECT CURRENT_DATE - INTERVAL (@row := @row + 1) DAY as dt, 0 as cal
  FROM activities t, (SELECT @row := -1) r
  WHERE @row < 30
) z
GROUP BY DATE(d)

请注意,我无法测试这两个查询中的任何一个;第二个可能有一些小的语法错误。如果结果不起作用,并且错误是不寻常的/您无法修复的东西,请告诉我。
调试:
单独运行每个查询。我不知道这会产生多少行:

SELECT  a.end_time as d, a.calories as c
  FROM activities a
  JOIN user_activities uc ON uc.activity_id = a.id
  WHERE uc.user_id = 1
  AND DATE(a.end_time) >= CURRENT_DATE - INTERVAL 29 DAY

这个应该有30行。如果没有,那是因为您没有使用至少有30行的表:

SELECT CURRENT_DATE - INTERVAL (@row := @row + 1) DAY as dt, 0 as cal
  FROM activities t, (SELECT @row := -1) r
  LIMIT 30

编辑:
修复了此错误-在联合后应用限制;这会产生不期望的结果

knsnq2tg

knsnq2tg2#

你可以试试下面-使用左连接

SELECT  DATE(a.end_time), SUM(a.calories)
FROM activities a
left JOIN user_activities uc ON uc.activity_id = a.id
Where uc.user_id = 1 AND DATE(a.end_time) >= CURRENT_DATE - INTERVAL 6 DAY
GROUP BY DATE(a.end_time) order by DATE(a.end_time) DESC
ncecgwcz

ncecgwcz3#

我试了一下,刚刚更新了 SUM(a.calories)IF(SUM(a.calories) IS NULL, 0, SUM(a.calories)) 你可以试试。。。

SELECT  DATE(a.end_time), IF(SUM(a.calories) IS NULL, 0, SUM(a.calories))
  FROM activities a
    JOIN user_activities uc ON uc.activity_id = a.id
  WHERE uc.user_id = 1
    AND
     DATE(a.end_time) >= CURRENT_DATE - INTERVAL 6 DAY
  GROUP BY DATE(a.end_time) DESC
w8rqjzmb

w8rqjzmb4#

此查询应符合以下要求:
cte动态地生成一个日期范围(这将上升到大约300年前)
结果是 LEFT JOIN 我被那个 activities 以及 user_activities table
这个 COALESCE 函数变为空 SUM 进入 0 价值观
查询:

WITH v AS (
    SELECT * FROM 
        (SELECT adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_date FROM
        (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
        (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
        (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
        (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
        (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) v
    WHERE selected_date BETWEEN CURRENT_DATE - INTERVAL 6 DAY AND CURRENT_DATE
)
SELECT v.selected_date, COALESCE(SUM(a.calories), 0)
FROM 
    v
    LEFT JOIN activities a on DATE(a.end_time) = v.selected_date
    LEFT JOIN user_activities uc ON uc.activity_id = a.id AND uc.user_id = 1
GROUP BY DATE(a.end_time) DESC
ORDER BY v.selected_date

相关问题