ITPub博客

首页 > 数据库 > MySQL > Session重叠问题学习(一)

Session重叠问题学习(一)

原创 MySQL 作者:壹頁書 时间:2015-12-10 10:41:19 0 删除 编辑
MySQL技术内幕 SQL
2.4 Session重叠问题

实验数据初始化:
  1. CREATE TABLE sessions (  
  2.     id INT AUTO_INCREMENT NOT NULL,   
  3.     app VARCHAR(10) NOT NULL,   
  4.     usr VARCHAR(10) NOT NULL,   
  5.     starttime TIME NOT NULL,   
  6.     endtime TIME NOT NULL,   
  7.     KEY (id)  
  8. );  
  9.   
  10. INSERT INTO sessions(app, usr, starttime, endtime)  
  11.   VALUES('app1', 'user1', '08:30', '10:30');  
  12. INSERT INTO sessions(app, usr, starttime, endtime)  
  13.   VALUES('app1', 'user2', '08:30', '08:45');  
  14. INSERT INTO sessions(app, usr, starttime, endtime)  
  15.   VALUES('app1', 'user1', '09:00', '09:30');  
  16. INSERT INTO sessions(app, usr, starttime, endtime)  
  17.   VALUES('app1', 'user2', '09:15', '10:30');  
  18. INSERT INTO sessions(app, usr, starttime, endtime)  
  19.   VALUES('app1', 'user1', '09:15', '09:30');  
  20. INSERT INTO sessions(app, usr, starttime, endtime)  
  21.   VALUES('app1', 'user2', '10:30', '14:30');  
  22. INSERT INTO sessions(app, usr, starttime, endtime)  
  23.   VALUES('app1', 'user1', '10:45', '11:30');  
  24. INSERT INTO sessions(app, usr, starttime, endtime)  
  25.   VALUES('app1', 'user2', '11:00', '12:30');  
  26. INSERT INTO sessions(app, usr, starttime, endtime)  
  27.   VALUES('app2', 'user1', '08:30', '08:45');  
  28. INSERT INTO sessions(app, usr, starttime, endtime)  
  29.   VALUES('app2', 'user2', '09:00', '09:30');  
  30. INSERT INTO sessions(app, usr, starttime, endtime)  
  31.   VALUES('app2', 'user1', '11:45', '12:00');  
  32. INSERT INTO sessions(app, usr, starttime, endtime)  
  33.   VALUES('app2', 'user2', '12:30', '14:00');  
  34. INSERT INTO sessions(app, usr, starttime, endtime)  
  35.   VALUES('app2', 'user1', '12:45', '13:30');  
  36. INSERT INTO sessions(app, usr, starttime, endtime)  
  37.   VALUES('app2', 'user2', '13:00', '14:00');  
  38. INSERT INTO sessions(app, usr, starttime, endtime)  
  39.   VALUES('app2', 'user1', '14:00', '16:30');  
  40. INSERT INTO sessions(app, usr, starttime, endtime)  
  41.   VALUES('app2', 'user2', '15:30', '17:00');  
  42.   
  43. CREATE UNIQUE INDEX idx_app_usr_s_e_key  
  44.   ON sessions(app, usr, starttime, endtime, id);  
  45. CREATE INDEX idx_app_s_e ON sessions(app, starttime, endtime);  



标记重叠的书中原文:

标示重叠是指为每个会话标示出相同应用程序和用户重叠的会话,即对于每个会话,标示出其内部的所有会话情况。
例如,app1、user1这个会话在08:30~10:30时间段内有3次重叠的会话:08:30~10:30、09:00~09:30和09:15~09:30。
对于这个问题,下面是完整的SQL解决方案:
  1. SELECT a.app, a.usr, a.starttime, a.endtime, b.starttime  
  2.     , b.endtime  
  3. FROM sessions a, sessions b  
  4. WHERE a.app = b.app  
  5.     AND a.usr = b.usr  
  6.     AND (b.endtime >= a.starttime  
  7.         AND b.starttime <= a.endtime)  

<b.starttime<b.endtime<a.endtime





分组重叠
还有一个问题是服务提供商可能允许多个session的连接,并把其计费统计为1次,这就是所谓的分组重叠。对于上面的例子,应该把app1、user1在08:30~10:30间的3次会话算为一次会话。
我们分步骤来讨论这个问题,先求出每个会话组开始时间,并用DISTINCT返回不重复的开始时间,具体过程如下:
  1. SELECT DISTINCT app, usr, starttime AS s  
  2. FROM sessions a  
  3. WHERE NOT EXISTS (SELECT *  
  4.     FROM sessions b  
  5.     WHERE a.app = b.app  
  6.         AND a.usr = b.usr  
  7.         AND a.starttime > b.starttime  
  8.         AND a.starttime <= b.endtime)  

用同样的方法得到会话组结束的时间,具体过程如下:
  1. SELECT DISTINCT app, usr, endtime AS e  
  2. FROM sessions a  
  3. WHERE NOT EXISTS (SELECT *  
  4.     FROM sessions b  
  5.     WHERE a.app = b.app  
  6.         AND a.usr = b.usr  
  7.         AND a.endtime >= b.starttime  
  8.         AND a.endtime < b.endtime)  

最后只需把两张表合并,并通过MIN函数取得结束的时间。完整的SQL解决方案如下面的代码所示:
  1. SELECT DISTINCT s.app, s.usr, s.s, (  
  2.         SELECT MIN(e)  
  3.         FROM (SELECT DISTINCT app, usr, endtime AS e  
  4.             FROM sessions a  
  5.             WHERE NOT EXISTS (SELECT *  
  6.                 FROM sessions b  
  7.                 WHERE a.app = b.app  
  8.                     AND a.usr = b.usr  
  9.                     AND a.endtime >= b.starttime  
  10.                     AND a.endtime < b.endtime)  
  11.             ) s2  
  12.         WHERE s2.e > s.s  
  13.             AND s.app = s2.app  
  14.             AND s.usr = s2.usr  
  15.         ) AS e  
  16. FROM (SELECT DISTINCT app, usr, starttime AS s  
  17.     FROM sessions a  
  18.     WHERE NOT EXISTS (SELECT *  
  19.         FROM sessions b  
  20.         WHERE a.app = b.app  
  21.             AND a.usr = b.usr  
  22.             AND a.starttime > b.starttime  
  23.             AND a.starttime <= b.endtime)  
  24.     ) s, (SELECT DISTINCT app, usr, endtime AS e  
  25.     FROM sessions a  
  26.     WHERE NOT EXISTS (SELECT *  
  27.         FROM sessions b  
  28.         WHERE a.app = b.app  
  29.             AND a.usr = b.usr  
  30.             AND a.endtime >= b.starttime  
  31.             AND a.endtime < b.endtime)  
  32.     ) e  
  33. WHERE s.app = e.app  
  34.     AND s.usr = e.usr  

</b.starttime<b.endtime<a.endtime

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-1869550/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2013-10-19

  • 博文量
    620
  • 访问量
    6339934