MySQL在正常表格中连续计数N天

MySQL在正常表格中连续计数N天,mysql,sql,datetime,database-normalization,Mysql,Sql,Datetime,Database Normalization,我想计算特定用户在给定日期及其之前连续召开会议的天数 例如:统计id为1的用户在2013年1月16日的连续会议天数 我找到了一些很好的答案,但是这些表格并不像我上面的示例那样以正常的形式出现,我不知道如何在我的场合实现它 示例表结构如下所示: CREATE TABLE IF NOT EXISTS `meetings` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `time` datetime NOT NULL, PRIMARY K

我想计算特定用户在给定日期及其之前连续召开会议的天数

例如:统计id为1的用户在2013年1月16日的连续会议天数

我找到了一些很好的答案,但是这些表格并不像我上面的示例那样以正常的形式出现,我不知道如何在我的场合实现它

示例表结构如下所示:

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                |
+---------+------------------+

像这样的怎么样。我希望它可以在没有子查询的情况下重新编写,但我一定有点大脑冻结了。。。修改数据集和查询以适应换档要求

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 |
 +---------+------------+------+ 

考虑为上面提供适当的DDL,包括一些插入和期望的结果。更好吗?是的,但它仍然不是真正具有代表性的,是吗!来吧,再多给我们一点…如果引擎是InnoDB,为什么不将密钥设为外键?对不起,忘记添加外键的代码了。现在添加它们。这些键确实是外来的。当一天有多个会议时,似乎计算错误。这可以通过在每个子查询中使用一个不同的+1 Catcall来轻松解决。另外,我只想指定一个日期来获取连续会议。我试着用从句,但运气不好。非常接近所以,根据我的数据集,在1月15日搜索用户id 1等于'2',对吗?谢谢你的解决方案运行良好。我刚刚意识到我不需要计算周末、周六、周日和跳过它们。。所以我想我得再问一个问题,嗯?