1

我有一个 MySQL 查询,用于确定一个只有 3 个的设备是否同时被四个并发事件使用。我有一个有效的查询,但它似乎效率低下,我很好奇是否有更好的方法来进行选择。

表结构(与查询无关的列已被删除) 该表目前包含大约 7-8k 行。

CREATE TABLE IF NOT EXISTS `tc_event` (
  `WorkOrderNumber` int(11) NOT NULL DEFAULT '0',
  `EventName` varchar(120) DEFAULT NULL,
  `CrewStartTime` datetime DEFAULT NULL,
  `CrewEndTime` datetime DEFAULT NULL,
  `SoundConsole` varchar(30) DEFAULT NULL,
  `Canceled` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`WorkOrderNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

当前(工作)查询:

SELECT UNIX_TIMESTAMP(T1.CrewStartTime) AS ConflictDate
            FROM tc_event T1, tc_event T2, tc_event T3, tc_event T4
            WHERE
                (T1.CrewStartTime BETWEEN T2.CrewStartTime AND T2.CrewEndTime)
                AND (T1.CrewStartTime BETWEEN T3.CrewStartTime AND T3.CrewEndTime)
                AND (T1.CrewStartTime BETWEEN T4.CrewStartTime AND T4.CrewEndTime)
                AND (T2.CrewSTartTime BETWEEN T3.CrewStartTime AND T3.CrewEndTime)
                AND (T2.CrewStartTime BETWEEN T4.CrewStartTime AND T4.CrewEndTime)
                AND (T3.CrewStartTime BETWEEN T4.CrewStartTime AND T4.CrewEndTime)
                AND T1.WorkOrderNumber != T2.WorkOrderNumber
                AND T1.WorkOrderNumber != T3.WorkOrderNumber
                AND T1.WorkOrderNumber != T4.WorkOrderNumber
                AND T2.WorkOrderNumber != T3.WorkOrderNumber
                AND T2.WorkOrderNumber != T4.WorkOrderNumber
                AND T3.WorkOrderNumber != T4.WorkOrderNumber
                AND T1.CrewStartTime > NOW()
                AND T1.SoundConsole = '12-Chan/PA-12'
                AND T2.SoundConsole = '12-Chan/PA-12'
                AND T3.SoundConsole = '12-Chan/PA-12'
                AND T4.SoundConsole = '12-Chan/PA-12'
                AND (T1.Canceled = 0 AND T1.EventName NOT LIKE '%*NOTC*%')
                AND (T2.Canceled = 0 AND T2.EventName NOT LIKE '%*NOTC*%')
                AND (T3.Canceled = 0 AND T3.EventName NOT LIKE '%*NOTC*%')
                AND (T4.Canceled = 0 AND T4.EventName NOT LIKE '%*NOTC*%')
            GROUP BY DATE(T1.CrewStartTime)
            ORDER BY T1.CrewStartTime

查询 EXPLAIN 语句:

查询解释

4

2 回答 2

1

首先将不等式更改为小于/大于比较。这也大大简化了事情:

SELECT UNIX_TIMESTAMP(T1.CrewStartTime) AS ConflictDate
        FROM tc_event T1, tc_event T2, tc_event T3, tc_event T4
        WHERE
            (T1.CrewStartTime BETWEEN T2.CrewStartTime AND T2.CrewEndTime)
            AND (T2.CrewSTartTime BETWEEN T3.CrewStartTime AND T3.CrewEndTime)
            AND (T3.CrewStartTime BETWEEN T4.CrewStartTime AND T4.CrewEndTime)
            AND T1.WorkOrderNumber < T2.WorkOrderNumber
            AND T2.WorkOrderNumber < T3.WorkOrderNumber
            AND T3.WorkOrderNumber < T4.WorkOrderNumber
            AND T1.CrewStartTime > NOW()
            AND T1.SoundConsole = '12-Chan/PA-12'
            AND T2.SoundConsole = '12-Chan/PA-12'
            AND T3.SoundConsole = '12-Chan/PA-12'
            AND T4.SoundConsole = '12-Chan/PA-12'
            AND (T1.Canceled = 0 AND T1.EventName NOT LIKE '%*NOTC*%')
            AND (T2.Canceled = 0 AND T2.EventName NOT LIKE '%*NOTC*%')
            AND (T3.Canceled = 0 AND T3.EventName NOT LIKE '%*NOTC*%')
            AND (T4.Canceled = 0 AND T4.EventName NOT LIKE '%*NOTC*%')
        GROUP BY DATE(T1.CrewStartTime)
        ORDER BY T1.CrewStartTime

之后,您最好在 上添加一个索引CrewStartTime,这应该对性能有很大帮助。您过滤的其他列上的索引也可能会有所帮助。

于 2013-06-24T23:12:07.260 回答
1

您只想知道是否存在冲突,即同时有 4 个用户。为此,您只需查看事件开始时间并检查有多少并发事件:

select soundconsole, st.CrewStartTime, count(*)
from (select distinct CrewStartTime, soundconsole
      from tc_event
     ) st join
     tc_event e
     on st.CrewStratTime between e.CrewStartTime and e.CrewEndTime and
        st.soundconsole = e.soundconsole
group by st.CrewStartTime, tc.soundconsole
having count(*) >= 4
于 2013-06-24T23:43:15.327 回答