2013-01-14 18 views
1

我想连续数天计算特定用户在指定日期和之前开会。MySQL在正常表格中连续N天计数

例如:数连续天会议,与ID 1用户有在1月16日2013年

我发现了一些很好的答案herehere但表不正常的形式就像我的样品上方和我无法弄清楚如何为我的场合实施它。

一个样本表结构如下:

CREATE TABLE IF NOT EXISTS `meetings` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `time` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE IF NOT EXISTS `meetings_users` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `user_id` int(10) unsigned NOT NULL, 
    `meeting_id` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `user_id` (`user_id`), 
    KEY `meeting_id` (`meeting_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE IF NOT EXISTS `users` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

-- 
-- Constraints for table `meetings_users` 
-- 
ALTER TABLE `meetings_users` 
    ADD CONSTRAINT `meetings_users_ibfk_2` FOREIGN KEY (`meeting_id`) REFERENCES `meetings` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    ADD CONSTRAINT `meetings_users_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 

样品插入

INSERT INTO `users` (`id`) VALUES (1) 

INSERT INTO `meetings` (`id`, `time`) VALUES 
(1, '2013-01-14 10:00:00'), 
(2, '2013-01-15 10:00:00'), 
(3, '2013-01-16 10:00:00') 


INSERT INTO `meetings_users` (`id`, `meeting_id`, `user_id`) VALUES 
(1, 1, 1), 
(2, 2, 1), 
(3, 3, 1) 

所需的输出:

*+---------+-----------------+ 
| user_id | consecutive_days | 
+---------+------------------+ 
|  1 | 3    | 
+---------+------------------+ 
+0

考虑上述提供适当的DDL,包括一些插入和期望的结果。 – Strawberry

+0

已编辑,现在好多了? –

+0

更好?是的,但它仍然不是真正具有代表性的!来吧,给我们多一点点... – Strawberry

回答

2

如何这样的事情。我希望它可以重新写入没有子查询,但我必须有一个有点脑冻的......(设定数据和查询修改,以适应转变的要求)

DROP TABLE IF EXISTS meetings; 
CREATE TABLE IF NOT EXISTS meetings 
(meeting_id int(10) unsigned NOT NULL AUTO_INCREMENT 
, meeting_time datetime NOT NULL 
, PRIMARY KEY (meeting_id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

DROP TABLE IF EXISTS meetings_users; 
CREATE TABLE IF NOT EXISTS meetings_users 
(user_id int(10) unsigned NOT NULL 
, meeting_id int(10) unsigned NOT NULL 
, PRIMARY KEY (meeting_id,user_id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

DROP TABLE IF EXISTS users; 
CREATE TABLE IF NOT EXISTS users 
(user_id int(10) unsigned NOT NULL AUTO_INCREMENT 
, PRIMARY KEY (user_id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

INSERT INTO users (user_id) VALUES (1),(2),(3),(4); 

INSERT INTO meetings (meeting_id, meeting_time) VALUES 
(1, '2013-01-14 10:00:00'), 
(2, '2013-01-15 10:00:00'), 
(3, '2013-01-16 10:00:00'), 
(4, '2013-01-17 10:00:00'), 
(5, '2013-01-18 10:00:00'), 
(6, '2013-01-19 10:00:00'), 
(7, '2013-01-20 10:00:00'), 
(8, '2013-01-14 12:00:00'); 


INSERT INTO meetings_users (meeting_id, user_id) VALUES 
(1, 1), 
(2, 1), 
(2, 3), 
(3, 1), 
(3, 3), 
(4, 2), 
(4, 3), 
(5, 2), 
(6, 1), 
(1, 8); 

SET @dt = '2013-01-15'; 

SELECT user_id 
    , start 
    , DATEDIFF(@dt,start)+1 cons 
    FROM 
    (
     SELECT a.user_id 
      , a.meeting_date Start 
      , MIN(c.meeting_date) End 
     , DATEDIFF(MIN(c.meeting_date),a.meeting_date) + 1 diff 
     FROM (SELECT DISTINCT mu.user_id,DATE(m.meeting_time) meeting_date FROM meetings_users mu JOIN meetings m ON m.meeting_id = mu.meeting_id) a 
     LEFT 
     JOIN (SELECT DISTINCT mu.user_id,DATE(m.meeting_time) meeting_date FROM meetings_users mu JOIN meetings m ON m.meeting_id = mu.meeting_id) b 
     ON b.user_id = a.user_id 
      AND a.meeting_date = b.meeting_date + INTERVAL 1 DAY 
     LEFT 
     JOIN (SELECT DISTINCT mu.user_id,DATE(m.meeting_time) meeting_date FROM meetings_users mu JOIN meetings m ON m.meeting_id = mu.meeting_id) c 
     ON c.user_id = a.user_id 
      AND a.meeting_date <= c.meeting_date 
     LEFT 
     JOIN (SELECT DISTINCT mu.user_id,DATE(m.meeting_time) meeting_date FROM meetings_users mu JOIN meetings m ON m.meeting_id = mu.meeting_id) d 
      ON d.user_id = a.user_id 
      AND c.meeting_date = d.meeting_date - INTERVAL 1 DAY 
     WHERE b.meeting_date IS NULL 
     AND c.meeting_date IS NOT NULL 
      AND d.meeting_date IS NULL 
     GROUP 
     BY a.user_id 
     , a.meeting_date 
    ) x 
WHERE @dt BETWEEN start AND end; 
+---------+------------+------+ 
| user_id | start  | cons | 
+---------+------------+------+ 
|  1 | 2013-01-14 | 2 | 
|  3 | 2013-01-15 | 1 | 
+---------+------------+------+ 
+1

当一天有多个会议时似乎错误计数。 –

+0

这可以很容易地在每个子查询 – Strawberry

+0

+1 Catcall中用DISTINCT修复。 另外我想指定只有一个日期获得连续会议。我试着用HAVING子句,但没有运气。 非常接近 –