【问题标题】:Need help on implementing loop in SQL query在 SQL 查询中实现循环需要帮助
【发布时间】:2016-02-15 08:23:31
【问题描述】:

我的 SQL Server 数据库中有两个表 FACULTY_RECORDSSCHOOL_RECORDS。我在表格FACULTY_RECORDS 中有包含学院所填写的关于他们参加的讲座的数据的行,以及包含学校分配给学院的时间段的行。

教师在表FACULTY_RECORDSLECTURE_START_TIME 列中以“10:15:00”格式填写他/她的讲座开始时间,学校以“0900-1200”格式提供给教师的时间段表SCHOOL_RECORDS 中的列LECTURE_TIME_SLOT

现在,我有一个 SQL 查询,用于检查教师为他的特定科目输入的时间是否在学校分配的时间段内。但是,通过 SQL 查询,我得到了多个输出行,因为相同的开始时间落在多个时隙中。然而,如果讲座开始时间落在为同一主题分配的时间段内,我要求查询仅提供一个输出。

请查看我的 SQL 查询:

SELECT 
    a.FACULTY, 
    a.SUBJECT, 
    a.LECTURE_DATE, 
    a.LECTURE_START_TIME 
FROM
    (SELECT
         b.LECTURE_TIME_SLOT, b.FACULTY, b.SUBJECT, b.LECTURE_DATE, 
         CAST(LEFT(b.LECTURE_TIME_SLOT, 2) + ':' + RIGHT(LEFT(b.LECTURE_TIME_SLOT, 4), 2) AS TIME) AS StartHours,
         CAST(LEFT(RIGHT(b.LECTURE_TIME_SLOT, 4), 2) + ':' + RIGHT(b.LECTURE_TIME_SLOT, 2) AS TIME) AS EndHours 
     FROM 
         @FACULTY_RECORDS AS a, @SCHOOL_RECORDS AS b) AS b 
JOIN
    @FACULTY_RECORDS AS a ON a.FACULTY = b.FACULTY 
                          AND a.SUBJECT = b.SUBJECT 
                          AND a.LECTURE_DATE = b.LECTURE_DATE 
WHERE
    CAST(a.LECTURE_START_TIME AS TIME) >= b.StartHours 
    AND CAST(a.LECTURE_START_TIME AS TIME) <= b.EndHours

请参考下图:

FACULTY_RECORDS & SCHOOL_RECORDS

Outputs: Lectures not matching & matching the time slots

【问题讨论】:

  • MySQL 不是 SQL Server。你用的是哪个?
  • 对不起。我使用的是 Microsoft SQL Server 2008 而不是 mysql。
  • 您好 Piero,感谢您提供的网址。我将尝试将sql查询修改为sql脚本,以检查它是否有效。
  • 如果讲座开始时间在两个时间段内... 你想要哪个时间段你想任意不显示一个吗?您获得多个输出行的原因是因为多个行符合条件。您需要考虑一些规则来选择其中之一。最简单和最简单的解决方案是选择第一次匹配的时间。但是第二次匹配呢?这也是一个有效的匹配。您的报告实际上试图显示什么?

标签: sql sql-server database sql-server-2008


【解决方案1】:

不清楚您为什么要使用 2 个表的隐含交叉联接(笛卡尔积)。如果有样本数据和预期的结果,这真的会有所帮助。如果没有这些,这有帮助吗?

select
     f.SUBJECT
   , f.LECTURE_DATE
   , f.LECTURE_START_TIME
   , s.StartTime
   , s.EndTime
FROM FACUTLY_RECORDS f
INNER JOIN (
        SELECT
             SUBJECT
           , LECTURE_DATE
           ,  CAST(LEFT(LECTURE_TIME_SLOT, 2) 
                 + ':' 
                 + substring(LECTURE_TIME_SLOT, 3, 2) AS time) AS StartTime
           , CAST(substring(LECTURE_TIME_SLOT, 6,2)
                 + ':' 
                 + RIGHT(LECTURE_TIME_SLOT, 2) AS time) AS EndTime
        FROM SCHOOL_RECORDS
      ) s  ON f.subject = s.subject
           AND f.LECTURE_DATE = s.LECTURE_DATE
           AND CAST(f.LECTURE_START_TIME AS time) BETWEEN s.StartTime AND s.EndTime
 ;

这是一种不使用时间转换的替代方法。尝试将“26:10:00”转换为时间并没有失败。它只列出两个表中的匹配项,因为它使用内部连接。

SELECT
      f.SUBJECT
    , f.LECTURE_DATE
    , f.LECTURE_START_TIME
    , s.StartTime
    , s.EndTime
FROM FACUTLY_RECORDS f
      INNER JOIN (
            SELECT
                  SUBJECT
                , LECTURE_DATE
                , LEFT(LECTURE_TIME_SLOT, 4) AS StartTime
                , RIGHT(LECTURE_TIME_SLOT, 4) AS EndTime
            FROM SCHOOL_RECORDS
      ) s ON f.subject = s.subject
                  AND f.LECTURE_DATE = s.LECTURE_DATE
                  AND replace(left(f.LECTURE_START_TIME,5),':','') BETWEEN s.StartTime AND s.EndTime
;  

我建议你提供更完整的测试数据,当然预期的结果仍然没有。

CREATE TABLE FACULTY_RECORDS
    ([FACULTY_NAME] varchar(4), [SUBJECT] varchar(7), [LECTURE_DATE] datetime, [LECTURE_START_TIME] varchar(8))
;

INSERT INTO FACULTY_RECORDS
    ([FACULTY_NAME], [SUBJECT], [LECTURE_DATE], [LECTURE_START_TIME])
VALUES
    ('Alex', 'Biology', '2015-01-10 00:00:00', '3:55:36'),
    ('Alex', 'Biology', '2015-01-10 00:00:00', '10:7:22'),
    ('Alex', 'Biology', '2015-01-10 00:00:00', '11:17:44')
;

CREATE TABLE SCHOOL_RECORDS
    ([FACULTY_NAME] varchar(4), [SUBJECT] varchar(7), [LECTURE_DATE] datetime, [LECTURE_TIME_SLOT] varchar(9))
;

INSERT INTO SCHOOL_RECORDS
    ([FACULTY_NAME], [SUBJECT], [LECTURE_DATE], [LECTURE_TIME_SLOT])
VALUES
    ('Alex', 'Biology', '2015-01-10 00:00:00', '0900-1200'),
    ('Alex', 'Biology', '2015-01-10 00:00:00', '0900-1200'),
    ('Alex', 'Biology', '2015-01-10 00:00:00', '0900-1200')
;

【讨论】:

  • 您好,此查询无效。我故意将 'LECTURE_START_TIME' 的值更改为 (26:10:00),并对照 'LECTURE_TIME_SLOT' 值 (0900-2400) 检查它。我可以在上述查询的输出中看到值“26:10:00”。理想情况下,它不应该反映在我的输出中。我猜 'BETWEEN' 子句不起作用?
  • 我再次故意将“LECTURE_START_TIME”的值更改为 (03:10:00),并对照“LECTURE_TIME_SLOT”值 (0900-2400) 进行了检查。我可以在上述查询的输出中看到值“03:10:00”。理想情况下,它不应该反映在我的输出中。对于开始时间为“03:10:00”的这一行,查询生成的 StartTime 和 EndTime 值为“NULL”
  • 使用内连接而不是左外连接。我会修改答案 foo
  • 您不断对我建议的查询进行查找的原因是因为您正在慢慢地揭示更多的数据和更多的需求。如果问题中提供了“LECTURE_START_TIME”作为 (26:10:00) 和 (03:10:00) 的测试用例,并且您显示或声明它们不应该出现在结果中 - 那么我会更多地了解它你需要吗?这就是为什么提供样本数据和预期结果如此重要的原因。
  • 这是我花费大部分时间在这里评论而不是发布答案的第一大原因。确定 OP 对该问题的承诺
猜你喜欢
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
  • 2011-05-29
  • 1970-01-01
  • 2016-07-04
  • 2016-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多