MySQL查询尚未分配的时间段的数据库

时间:2011-04-13 03:11:19

标签: mysql time

我有一个相当复杂的看似查询,它将构成在线课堂安排工具的基础。我的挑战是开发一种方法来识别用户在st_schedule表中注册的类,然后从类的整个表中推断出st_classes,哪些其他类是可用的,与用户的当前类不冲突。 / p>

例如,如果用户在st_schedule中有一个条目,从早上8点到早上9点将它们分配给一个班级,那么他们就没有资格参加上午8:00到9:00之间的任何班级。上午7:15 - 上午8:15运行的课程会使用户不合格。我将类的开始时间和结束时间分别存储在数据库中以进行比较。重要的是,这应该尽可能灵活,因此“阻塞”时间和为块分配时间的概念是不可能的。

以下是表格的摘录:

table st_classes (holds class information)
id
start_time
end_time

table st_schedule (holds schedule information)
id
user_id
class_id

我当然可以在服务器端的一系列循环中执行此操作,但我必须认为有一种MySQL方法可以一举完成这种类型的操作。

2 个答案:

答案 0 :(得分:3)

您希望将两个表连接在一起以表示用户的类,然后查找未注册的类,其中开始时间和结束时间不在用户类的开始和结束时间之间。

像这样的东西。完全脱下袖口,未经测试:

SELECT
    *
FROM
    st_schedule s
    INNER JOIN st_classes c ON c.id = s.class_id
    INNER JOIN st_classes all_classes 
        ON all_classes.start_time NOT BETWEEN c.start_time AND c.end_time
        AND all_classes.end_time NOT BETWEEN c.start_time AND c.end_time
WHERE
   s.user_id = 1

编辑:尝试#2 我只有一点时间来看看这个。我想我颠倒了第二个连接条款。 all_classes别名表示完整的类列表,其中“c”别名表示学生注册的类。

SELECT DISTINCT
    all_classes.*
FROM
    st_schedule s
    INNER JOIN st_classes c ON c.id = s.class_id
    INNER JOIN st_classes all_classes 
        ON c.start_time NOT BETWEEN all_classes.start_time AND all_classes.end_time
        AND c.end_time NOT BETWEEN all_classes.start_time AND all_classes.end_time
WHERE
   s.user_id = 1

答案 1 :(得分:1)

这是在mssql中使用表变量,但是sql选择应该转换为mysql

首先是样本数据

DECLARE @st_classes TABLE
    (
     ID INT NOT NULL,
     Title VARCHAR(40) NOT NULL,
     StartTime DATETIME NOT NULL,
     EndTime DATETIME NOT NULL
    )       

DECLARE @st_schedule TABLE
    (
     ID INT NOT NULL,
     UserID INT NOT NULL,
     ClassID INT NOT NULL
    )       

INSERT INTO @st_classes (ID, Title, StartTime, EndTime)
SELECT 1,'Class1','08:00:00','09:30:00' UNION 
SELECT 2,'Class2','09:30:00','11:30:00' UNION
SELECT 3,'Class3','11:30:00','16:00:00' UNION
SELECT 4,'Class4','16:00:00','17:30:00' UNION
SELECT 5,'Class5','09:00:00','11:45:00' UNION
SELECT 6,'Class6','07:00:00','18:00:00' 

INSERT INTO @st_schedule(ID, UserID, ClassID)
SELECT 1,1,1 UNION
SELECT 2,1,2 UNION
SELECT 3,2,6

接下来一点sql确认表加入OK(为ID为1的用户选择预定课程) - 返回1级和2级

SELECT *
FROM    @st_schedule AS S INNER JOIN 
        @st_classes AS C ON S.ClassID = C.ID
WHERE  S.UserID = 1 

现在我们需要选择与时间明确重叠的课程的所有课程ID(包括预定课程) - 返回1,2,5,6

SELECT  AC.ID
FROM    @st_classes AS AC
        INNER JOIN ( SELECT C.StartTime,
                            C.EndTime
                     FROM   @st_schedule AS S
                            INNER JOIN @st_classes AS C ON S.ClassID = C.ID
                     WHERE  S.UserID = 1
                   ) AS UC ON ( AC.StartTime < DATEADD(ss, -1, UC.EndTime)
                                AND DATEADD(ss, -1, UC.EndTime) > UC.StartTime
                              )
GROUP BY AC.ID 

现在我们需要选择课程ID不在重叠课程ID列表中的所有课程。 - 返回课程3和4

SELECT  *
FROM    @st_classes
WHERE   ID NOT IN (
        SELECT  AC.ID
        FROM    @st_classes AS AC
                INNER JOIN ( SELECT C.StartTime,
                                    C.EndTime
                             FROM   @st_schedule AS S
                                    INNER JOIN @st_classes AS C ON S.ClassID = C.ID
                             WHERE  S.UserID = 1
                           ) AS UC ON ( AC.StartTime < DATEADD(ss, -1, UC.EndTime)
                                        AND DATEADD(ss, -1, UC.EndTime) > UC.StartTime
                                      )
        GROUP BY AC.ID )

将用户ID过滤器更改为2,因为分配给该用户的课程与所有课程重叠,所以不应返回任何内容。