这是我的表结构:
// reputations
+----+-------+---------------+
| id | value | date_time |
+----+-------+---------------+
| 1 | 5 | 1472105459 | -- in last month
| 2 | -2 | 1472105460 | -- in last month
| 3 | 15 | 1472746410 | -- in last week
| 4 | 5 | 1472746421 | -- in last week
| 5 | 10 | 1472746432 | -- in last week
| 6 | -6 | 1473115566 | -- yesterday
| 7 | 2 | 1473205567 | -- today
| 8 | 10 | 1473205590 | -- today
+----+-------+---------------+
我需要求和 value
列并根据这些逻辑对它们进行分组:
(CASE WHEN FROM_UNIXTIME(MAX(date_time)) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day
所以这是预期的结果:
+----+-------+---------------+
| id | value | date_time |
+----+-------+---------------+
| 2 | 3 | 1472105460 | -- in last month
| 5 | 30 | 1472746432 | -- in last week
| 6 | -6 | 1473115566 | -- yesterday
| 8 | 12 | 1473205590 | -- today
+----+-------+---------------+
好吧,我怎么能这样做?
我想我没有正确地提出我的问题。让我问另一种方式: 这是我的表结构:
// votes
+----+-------+-----------+---------------+
| id | value | post_id | date_time |
+----+-------+-----------+---------------+
| 1 | 5 | 1 | 1472105459 | -- in last month
| 2 | -2 | 2 | 1472105460 | -- in last month
| 3 | 10 | 2 | 1472746410 | -- in last week
| 4 | 5 | 1 | 1472746421 | -- in last week
| 5 | 10 | 3 | 1472746432 | -- in last week
| 6 | 5 | 1 | 1473115566 | -- in last week
| 7 | -2 | 1 | 1473205567 | -- yesterday
| 8 | 10 | 1 | 1473205590 | -- yesterday
+----+-------+-----------+---------------+
我想要这个输出:
// votes
+----+-------+-----------+---------------+---------------+
| id | value | post_id | date_time | range_day |
+----+-------+-----------+---------------+---------------+
| 1 | 5 | 1 | 1472105459 | in last month |
| 2 | -2 | 2 | 1472105460 | in last month |
| 3 | 10 | 2 | 1472746410 | in last week |
| 5 | 10 | 3 | 1472746432 | in last week |
| 6 | 10 | 1 | 1473115566 | in last week |
| 8 | 8 | 1 | 1473205590 | yesterday |
+----+-------+-----------+---------------+---------------+
如您所见,我根据post_id
和range_day
对它们进行了分组。注意到当某些行合并时我需要保留最大的date_time
。
我该怎么做?
答案 0 :(得分:3)
我认为你过于复杂了。只需在CASE语句中删除MAX()
即可。然后你可以GROUP BY range_day
。
SELECT MAX(id) as id,
SUM(value) as value,
(CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day
FROM reputations
GROUP BY range_day
http://sqlfiddle.com/#!9/39e58c/1
现在SQLFidde返回:
| id | value | range_day |
|----|-------|---------------|
| 2 | 3 | in last month |
| 6 | 24 | in last week |
| 8 | 12 | yesterday |
这不等于您的预期结果。但那是因为时间不是常数。 Tomorow你会得到另一个结果。
<强>更新强>
您正在尝试使用无效且不合理的代码来解释您的问题。但是看看你的预期结果,我想你想按特定的日期范围进行分组。所以让我们先转换你的表:
SELECT id,
value,
DATE(FROM_UNIXTIME(date_time)) as dt,
CURDATE() as today,
(CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day
FROM reputations
| id | value | dt | today | range_day |
|----|-------|--------------------|--------------------|---------------|
| 1 | 5 | August, 25 2016 | September, 07 2016 | in last month |
| 2 | -2 | August, 25 2016 | September, 07 2016 | in last month |
| 3 | 15 | September, 01 2016 | September, 07 2016 | in last week |
| 4 | 5 | September, 01 2016 | September, 07 2016 | in last week |
| 5 | 10 | September, 01 2016 | September, 07 2016 | in last week |
| 6 | -6 | September, 05 2016 | September, 07 2016 | in last week |
| 7 | 2 | September, 06 2016 | September, 07 2016 | yesterday |
| 8 | 10 | September, 06 2016 | September, 07 2016 | yesterday |
现在让我们用“手”分组结果:
如果您想要每个组的“最大date_time”,只需将FROM_UNIXTIME((MAX(date_time))
添加到SELECT子句中。
更新2:
刚刚意识到预期结果中的date_time
列。所以这就是你得到它的方式:
SELECT MAX(id) as id,
SUM(value) as value,
MAX(date_time) as date_time
FROM reputations
GROUP BY
CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END
ORDER BY id
更新3
这应该可以解决您的更新问题:
SELECT
MAX(id) as id,
SUM(value) as value,
post_id,
MAX(date_time) as date_time,
(CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day
FROM votes
GROUP BY post_id, range_day
ORDER BY id
答案 1 :(得分:1)
您不能在CASE语句中使用MAX()。它将返回该领域的全局最大值。基本上是单行。相反,您需要按范围分组,然后选择local max:
SELECT a.`value`, a.date_time FROM
(SELECT sum(`value`) as `value`,
(CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day, MAX(date_time) as date_time
FROM reputations
GROUP BY 2) a
ORDER BY 2 ASC