获取特定数据以及分组依据

时间:2016-03-10 16:41:51

标签: mysql

我有一张名为log的表。

表: log

ID    user_id    time_of_action

我想为每个用户获取每个日期i.e. group by date,user_id的结果。

所以,这是预期的输出结构:

user_id     date    occurred_in_afternoon     occurred_at_night   total_action_count

解释

happen_in_afternoon:用户的任何操作是否发生在12:00 PM4:00 PM之间

happen_at_night:是否在8:00 PM12:00 AM(第二天)之间发生了任何用户操作

架构和示例数据:

DROP TABLE IF EXISTS `logs`;
CREATE TABLE `logs` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `time_of_action` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`Id`)
);


INSERT INTO `logs` VALUES ('1', '71', '2016-03-10 10:07:34');
INSERT INTO `logs` VALUES ('2', '66', '2016-03-10 14:07:57');
INSERT INTO `logs` VALUES ('3', '71', '2016-03-10 22:08:27');
INSERT INTO `logs` VALUES ('4', '71', '2016-03-10 15:08:40');

这是我目前的疑问:

SELECT 
user_id,
DATE(time_of_action) `date`,
CASE WHEN time_of_action BETWEEN TIMESTAMPADD(HOUR,12,DATE(time_of_action)) AND TIMESTAMPADD(HOUR,16,DATE(time_of_action))  THEN 1 ELSE 0 END occurred_in_afternoon,
CASE WHEN time_of_action BETWEEN TIMESTAMPADD(HOUR,20,DATE(time_of_action)) AND TIMESTAMPADD(HOUR,24,DATE(time_of_action))  THEN 1 ELSE 0 END occurred_at_night,
COUNT(*) total_action_count
FROM `logs`
GROUP BY `date`,user_id

我目前的输出:

user_id       date       occurred_in_afternoon       occurred_at_night    total_action_count
66           2016-03-10         1                       0                        1
71           2016-03-10         0                       0                        3

预期输出:

user_id       date       occurred_in_afternoon       occurred_at_night    total_action_count
66           2016-03-10         1                       0                        1
71           2016-03-10         1                       1                        3

问题是我没有得到预期的结果。我想下午发生的值会被另一个time_of_action重置,而这个时间不在那个下午的区域。 是否可以在单个查询中实现它?

2 个答案:

答案 0 :(得分:1)

您错过了使用聚合函数。您可以将MAX()BIT_OR()用于您的目的:

SELECT 
user_id,
DATE(time_of_action) `date`,
MAX(CASE WHEN time_of_action BETWEEN TIMESTAMPADD(HOUR,12,DATE(time_of_action)) AND TIMESTAMPADD(HOUR,16,DATE(time_of_action))  THEN 1 ELSE 0 END) occurred_in_afternoon,
MAX(CASE WHEN time_of_action BETWEEN TIMESTAMPADD(HOUR,20,DATE(time_of_action)) AND TIMESTAMPADD(HOUR,24,DATE(time_of_action))  THEN 1 ELSE 0 END) occurred_at_night,
COUNT(*) total_action_count
FROM `logs`
GROUP BY `date`,user_id

更新:我还希望使用更易阅读的版本,例如

SELECT 
    user_id,
    DATE(time_of_action) `date`,
    BIT_OR(TIME(time_of_action) BETWEEN '12:00:00' AND '16:00:00') occurred_in_afternoon,
    BIT_OR(TIME(time_of_action) BETWEEN '20:00:00' AND '23:59:59') occurred_at_night,
    COUNT(*) total_action_count
FROM `logs`
GROUP BY `date`,user_id

答案 1 :(得分:0)

我正在考虑使用SUM获得的结果表的别名,以便为这两个字段获取Binary value

SELECT 
t.user_id,
t.date,
CASE WHEN t.occurred_in_afternoon > 0 THEN 1 ELSE 0 END AS occurred_in_afternoon,
CASE WHEN t.occurred_at_night > 0 THEN 1 ELSE 0 END AS occurred_at_night,
t.total_action_count
FROM 
(SELECT 
user_id,
DATE(time_of_action) `date`,
SUM(CASE WHEN time_of_action BETWEEN TIMESTAMPADD(HOUR,12,DATE(time_of_action)) AND TIMESTAMPADD(HOUR,16,DATE(time_of_action))  THEN 1 ELSE 0 END) occurred_in_afternoon,
SUM(CASE WHEN time_of_action BETWEEN TIMESTAMPADD(HOUR,20,DATE(time_of_action)) AND TIMESTAMPADD(HOUR,24,DATE(time_of_action))  THEN 1 ELSE 0 END) occurred_at_night,
COUNT(*) total_action_count
FROM `logs`
GROUP BY `date`,user_id) t