我正在尝试总结特定用户在过去7天(实际天是第7天)每天的活动卡路里。有表用户和活动表,以及映射表user_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
这是正确的,但是现在我的问题是,正如您在列表中看到的那样,未列出12-23-2018,因为该日期没有活动。现在我要显示
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
表:
答案 0 :(得分:0)
您可以尝试以下操作-使用左联接
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
答案 1 :(得分:0)
如果您的活动表很可能在特定的一天没有列出活动,则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的方法依赖于活动表中每天有一条记录。这是解决问题的有效方法,但是您还没有具体说明这些表包含哪些数据(提示:发布数据库问题时,请务必包括每个表的示例数据)
使用这种方法,我们可以像往常一样进行查找,但是我们还会生成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
编辑:
已修复此错误-合并后应用了LIMIT;这会产生不良结果
答案 2 :(得分:0)
我正在尝试,只是将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
答案 3 :(得分:0)
此查询应达到目的:
LEFT JOIN
和activities
表user_activities
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