2014-09-21 21 views
2

我有一個事件/日曆MySQL表,其中每個用戶在一天中有多個約會/事件。如果一個用戶因爲他/她在其他約會中跑步而無法進行該預約/事件「我需要能夠將該約會重新分配給不同的可用用戶。因此,我需要顯示在預定時間範圍內可用的前5位用戶的建議,並且可以進行此預約,經理將能夠將該預約重新分配給建議用戶之一。如何從日曆數據庫獲取可用時間段的列表

我的活動表看起來像這樣

CREATE TABLE `calendar_events` (
    `event_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `start_on` datetime NOT NULL, 
    `end_on` datetime NOT NULL, 
    `subject` varchar(255) NOT NULL, 
    `event_type` enum('Phone Call','Meeting','Event','Appointment','Other') CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT 'Phone Call', 
    `all_day_event` tinyint(1) DEFAULT '0' COMMENT '1 = all day event, 0 = no', 
    `phone_call_id` int(11) unsigned DEFAULT NULL, 
    `account_id` int(11) unsigned DEFAULT NULL, 
    `client_id` int(11) unsigned DEFAULT NULL, 
    `owner_id` int(11) unsigned NOT NULL, 
    `created_by` int(11) unsigned NOT NULL, 
    `created_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `modified_by` int(11) unsigned DEFAULT NULL, 
    `modified_on` datetime DEFAULT NULL, 
    `event_location` varchar(255) DEFAULT NULL, 
    `event_notes` varchar(10000) DEFAULT NULL, 
    `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 = purged, 1 = active, 2=pass, 3 = cancled, 5 = waiting for auditor to be enabled', 
    PRIMARY KEY (`event_id`), 
    UNIQUE KEY `phone_call_id` (`phone_call_id`,`account_id`,`client_id`), 
    KEY `client_id` (`client_id`), 
    KEY `account_id` (`account_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

所以讓我們的事項標識= 100被分配到user_id說明= 2,定於START_ON = '2014年9月21日10:00:00' 和end_on「 2014-09-21 10:00:00'

and user_id = 5 has appointment start_on'2014-09-21 11:45:00'and end_on'2014-09-21 12:30:00'

和user_id = 2無法預約'2014-09-21 10:00:00',因此他們的系統會建議user_id = 5,因爲他將會接下來的105分鐘。

的最終數據集將需要

event_id org_owner suggested_owner available_for 
100  2   5     105 

下面的查詢會給我所有可用的用戶列表從users表與START_ON end_on值一起,如果用戶有一個事件安排(一個用戶可以有多個記錄。)如果此查詢中的start_on爲空,則表示此用戶沒有任何事件,否則將返回每個事件的開始。

因此,如果用戶ID出現在上面的查詢中,並且在start_on列中有一個NULL值,這意味着該用戶可以整天使用,因此該用戶應該是推薦的5個用戶中的1個,因爲它具有最高可用性。但是,如果用戶在數據集中有一個/多個行,並且開始時的值爲非空值,那麼我們需要查看離事件最近的start_on,然後推薦具有最高可用性的前5個值。

SELECT user_id, start_on, end_on, subject 
FROM view_users AS su 
LEFT JOIN calendar_events AS c ON c.owner_id = su.user_id AND c.start_on NOT BETWEEN '2014-09-30 00:00:00' AND '2014-09-30 23:59:59' AND c.status = 1 
WHERE su.is_available_today = 1 

如何提取此數據集?

回答

0

感謝您的幫助而編輯的第一個建議,只需要照顧沒有任何事件的用戶(可以通過't'子查詢中的左連接實現)。這可能是提高了很多,但現在我有點累了:)

SELECT 
c.event_id,      -- Event id 
c.owner_id AS org_owner,  -- Original owner of event 
t.owner_id AS suggested_owner, -- Suggested new user 
c.start_on,      -- Event start 
t.free_from,     -- Owner free slot start 
t.free_to,     -- Owner free slot end 
TIME_TO_SEC(TIMEDIFF(t.free_to, c.start_on)) /60 AS available_for -- Availibility of minutes (diff between event start and free slot end) 

FROM calendar_events AS c 

-- Join with free slots 
LEFT JOIN (
    -- Add a slot for beginning, 1999-01-01 to first event start 
    SELECT * FROM (
     SELECT owner_id, '1900-01-01' AS free_from, MIN(start_on) AS free_to 
     FROM calendar_events c3 
     GROUP BY owner_id 
    ) AS deb 

    UNION 

    -- select free slots by taking the event end and the following event start 
    SELECT owner_id, `end_on` AS free_from, (
     SELECT start_on 
     FROM calendar_events c2 
     WHERE c2.owner_id = c1.owner_id 
     AND c2.start_on > c1.end_on 
     ORDER BY c2.start_on 
     LIMIT 0 , 1 
    ) AS free_to 

    FROM calendar_events c1 

    UNION 

    -- Add a slot for end, last event end to 2100-01-01 
    SELECT * FROM (
     SELECT owner_id, MAX(end_on) AS free_from, '2100-01-01' AS free_to 
     FROM calendar_events c3 
     GROUP BY owner_id 
    ) AS end 
) AS t ON t.owner_id <> c.owner_id 
-- Join avoid using same user and ensure free slot matches event dates 
AND t.free_from <= c.start_on AND t.free_to >= c.end_on 
WHERE c.status = 1 
AND c.event_id =52 
GROUP BY t.owner_id  -- To avoid multiple free slots by user 
ORDER BY available_for DESC -- Sort to list biggest slots first 
LIMIT 0, 5    -- Only five first matching users 

祝你好運:)

+0

它無法正常工作。另外,event_type不應該是因素。無論事件類型如何,每個人都可以參加下一次預約。不工作意味着建議的所有者與org_owner的名稱相同。 org_owner必須不同於作爲建議所有者的suggested_owner是新的可用用戶。 – Jaylen 2014-09-30 22:21:31

+0

我創建了表格並填充了數據,它似乎在爲我工作。你能提供一小部分數據嗎?謝謝編輯:剛剛看到關於名稱的解釋,它會通過添加'cal_avail.owner_id <> calendar_events.user_id'最後'on'子句工作嗎? – nicolas 2014-09-30 22:23:39

+0

這並沒有奏效。這裏是我用一些數據創建的小提琴給你一些數據http://sqlfiddle.com/#!9/8374f/1通知,查詢我縮小查詢event_id = 52,所以我可以找到3個建議用戶 – Jaylen 2014-09-30 22:39:15

0

如何:

SELECT event_id, owner_id, start_on INTO @eventid, @user, @start_on 
FROM calender_events WHERE event_id = 100; 

SELECT @event_id event_id, 
    @user org_owner, 
    c.owner_id suggested_owner, 
    TIMESTAMPDIFF(MINUTE, $start_on, COALESCE(c.min_start, DATE(@start_on) + INTERVAL 18 HOUR)) available_for 
FROM 
    users u 
LEFT JOIN 
    (SELECT 
      owner_id, 
      MIN(start_on) 
    FROM 
      calender_events 
    WHERE 
      (start_on BETWEEN @start_on AND DATE(@start_on) + INTERVAL 18 HOUR) 
      OR 
      (start_on BETWEEN DATE(@start_on) AND DATE(@start_on) + INTERVAL 18 HOUR AND all_day_event = 1) 
    GROUP BY owner_id 
    ) c 
    ON u.user_id = c.owner_id 
WHERE u.user_id <> @user 
ORDER BY available_for DESC 
LIMIT 5 

也許你有調整INTERVAL,我只是假設了下午6點結束

+0

注意:您必須執行兩個查詢 – Gervs 2014-10-01 16:16:53

0

試試這個:

SELECT 
    co.event_id, 
    co.owner_id org_owner, 
    su.user_id suggested_owner, 
    ifnull(min((to_seconds(c.start_on) - to_seconds(co))/60), 999) available 
FROM calendar_events co 
CROSS JOIN view_users su 
LEFT JOIN calendar_events c ON c.owner_id = su.user_id 
    AND c.start_on BETWEEN co.start_on AND date(adddate(co.start_on, 1)) 
    AND c.status = 1 
WHERE co.event_id = 100 
AND su.is_available_today = 1 
GROUP BY 1, 2, 3 
ORDER BY 4 DESC 
LIMIT 5 

用戶有沒有預約日復一日目標事件得到分配的「999」可用的價值,使他們在列表的頂部。

每個用戶的下一個事件是使用min()在時間間隔中發現,所有的用戶都最大時間間隔第一排序,他們limit給你的前5名

相關問題