Session重疊問題學習(一)

壹頁書發表於2015-12-10
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部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1869550/,如需轉載,請註明出處,否則將追究法律責任。

相關文章