1

In a previous question about "count N consecutive days in normal form tables" i got this answer below that works fine. I realized that i need to skip counting the weekends, for example: if a user has a meeting on Friday and on next Monday then this should count as 2 consecutive days and not brake because of the weekends.

Here is the code that explains what i have now.

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-11 10: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),
(8, 1);

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

I tried creating my own function to replace original DATEDIFF in order to skip weekends based on this answer(i named it CustomDateDiff) and is working pretty fine, but i think that the problem persists on a.meeting_date = b.meeting_date + INTERVAL 1 DAY where i should skip the INTERVAL too i guess.

Community
  • 1
  • 1
Vassilis Barzokas
  • 3,105
  • 2
  • 26
  • 41

1 Answers1

2

OK, grabbing a bit of code from here, I've amended my previous response to factor in @dt...

@dt = '2013-01-15';
SELECT *
     , @dt target
     , 5 * (DATEDIFF(@dt, start) DIV 7) + MID('0123444401233334012222340111123400001234000123440', 7 * WEEKDAY(start) + WEEKDAY(@dt) + 1, 1)+1 cons
FROM (
    SELECT x.user_id
         , MIN(x.start) start
         , COALESCE(y.end,x.end) end
         , MAX(COALESCE(y.diff,0)+x.diff) ttl
      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
    LEFT JOIN
       (
         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
    )y
    ON y.user_id = x.user_id
    AND y.start = x.end+INTERVAL 3 DAY AND WEEKDAY(x.end) = 4
    GROUP BY user_id,end
)j
WHERE @dt BETWEEN start AND end;
Community
  • 1
  • 1
Strawberry
  • 33,750
  • 13
  • 40
  • 57
  • Thanks. Just tested it and it doesn't seem to work as it should. In the original example i set the meeting with id = 1 to have meeting_time = "2013-11-01" meeting with id = 2 to "2013-15-01" and meeting with id = 3 to "2013-16-01" (which are both related to user_id = 1) and it splits the meetings to 1 and 2 consecutive days. What i want is to count it as one meeting with 3 days. – Vassilis Barzokas Jan 15 '13 at 13:23
  • But then I'm confused. The 15th (today) is a Tuesday. User 1 has no meetings on Monday, so there's a gap. !?!?! – Strawberry Jan 15 '13 at 13:55
  • ohh sorry again, forgot to add the "2013-01-14" to the explanation of my example above. I have set the correct formating and Jan 11, 14, 15, 16 to user 1. It shows 1 meeting at 11 and 3 meetings from 14-16. It should show 4 meetings from 11-16. Have you tried it and it is working?? – Vassilis Barzokas Jan 15 '13 at 13:58
  • I think we need to see the complete DDLs (CREATE and INSERT statements) that you think you're working with! Just edit your post at the top. – Strawberry Jan 15 '13 at 13:59
  • Ok i have edited my original answer to include my DDLs as i explained them above. – Vassilis Barzokas Jan 15 '13 at 14:05
  • I am trying to alter it a bit in order to use the @dt variable, with no luck. Could you revise your answer to fit it? – Vassilis Barzokas Jan 15 '13 at 16:57