2

下面的 SQL 查询应该显示教师的可用性。有 3 种可能的预订类型 - 上午、下午或全天。如果有上午预订,则单元格中的文本应显示下午,如果有下午预订,则应显示上午,如果有全天预订,或上午和下午预订,则应显示“xxx”。

这在凌晨 1 点、下午 1 点或 1 全天预订时一切正常,但如果在同一天有凌晨 1 点和下午 1 点,它不会显示 XXX,因为我使用的是 MIN()。我怎样才能让它在一天内评估所有预订,而不是最小的预订?(你可以看到我试图在星期四的代码部分说明我的意思。

SQL:

with CTE_D as 
( 
   SELECT 
      DATEADD(ww, DATEDIFF(ww,0,GETDATE()), 0) as BookingDate 

   UNION ALL

   SELECT
      DATEADD(day, 1, BookingDate) 
   FROM
      CTE_D 
   WHERE
      BookingDate < DATEADD(ww, DATEDIFF(ww,0,GETDATE()), 6) 
)
SELECT 
    t.ID, t.Firstname, 
    t.Surname, tb.Band, t.Telephone, t.Mobile, t.Teacher, t.TeacherAssistant, t.PrimarySchool, t.SecondarySchool,
    MIN(CASE WHEN bd.DayText = 'Monday' AND bd.BookingDuration = 0 THEN 'PM' ELSE 'Full Day' END) "Monday", 
    MIN(CASE WHEN bd.DayText = 'Tuesday' AND bd.BookingDuration = 0 THEN 'PM' ELSE 'Full Day' END) "Tuesday", 
    MIN(CASE WHEN bd.DayText = 'Wednesday' AND bd.BookingDuration = 0 THEN 'PM' ELSE 'Full Day' END) "Wednesday", 
    MIN(CASE WHEN bd.DayText = 'Thursday' AND bd.BookingDuration = 0 THEN 'PM' WHEN bd.DayText = 'Thursday' AND bd.BookingDuration = 1 THEN 'AM' WHEN bd.DayText = 'Thursday' AND bd.BookingDuration = 2 or (bd.BookingDuration = 1 and bd.BookingDuration = 0) THEN 'xxx' END) "Thursday", 
    MIN(CASE WHEN bd.DayText = 'Friday' AND bd.BookingDuration = 0 THEN 'PM' ELSE 'Full Day' END) "Friday",
    Notes 
        FROM Teachers t 
        cross join CTE_D d 
        left join BookingDays bd 
            on t.ID = bd.TeacherID and 
               bd.BookingDate = d.BookingDate 
        left join BookingDurations bds 
            on bd.BookingDuration = bds.ID 
        left join TeacherBands tb on t.Band = tb.ID
        WHERE t.Active = 0 and (t.Status = 0 or t.Status = 1) and (bd.Status = 0 or bd.Status IS NULL) and PrimarySchool = 1
        GROUP BY Firstname, Surname, t.Telephone, t.Mobile, t.Notes, tb.Band, t.ID, t.Teacher, t.TeacherAssistant, t.PrimarySchool, t.SecondarySchool, t.Nursery, t.Reception, t.Year1, t.Year2, t.Year3, t.Year4, t.Year5, t.Year6, t.Year7, t.Year8, t.Year9, t.Year10, t.Year11, t.ALevel
        ORDER BY Surname, Firstname ASC

表列:

ID | Firstname | Surname | Band | Telephone | Mobile | Teacher | Teacher Assistant | PrimarySchool | SecondarySchool | KeyStage | Mon | Tues | Wed | Thurs | Fri | Notes

谢谢,马特

4

1 回答 1

4

我认为问题在于您正在尝试同时执行 2 个需要分开的操作(检查工作日,并检查预订持续时间)。为此,我假设您的预订时长为:

  • 0 - 下午
  • 1 - 上午
  • 2 - 全天

如果这不正确,您将需要稍微调整我的查询,但这应该会让您走上正轨。我还假设预订表中没有记录意味着不可用:

SET LANGUAGE British;

WITH Bookings AS
(   SELECT  BookingDays.TeacherID,
            [WeekDay] = DATENAME(WEEKDAY, BookingDate),
            [Status] = CASE WHEN BookingDuration = 0 THEN 'PM' WHEN BookingDuration = 1 THEN 'AM' ELSE 'Full Day' END
    FROM    BookingDays
), PivotedBookings AS
(   SELECT  *
    FROM    Bookings
            PIVOT
            (   MAX([Status])
                FOR [WeekDay] IN ([Monday], [Tuesday], [Wednesday], [Thursday], [Friday])
            ) pvt
)
SELECT  t.ID, 
        t.Firstname, 
        t.Surname, 
        tb.Band, 
        t.Telephone, 
        t.Mobile, 
        t.Teacher, 
        t.TeacherAssistant, 
        t.PrimarySchool, 
        t.SecondarySchool,
        Monday = COALESCE(pb.Monday, 'Not Available'),
        Tuesday = COALESCE(pb.Tuesday, 'Not Available'),
        Wednesday = COALESCE(pb.Wednesday, 'Not Available'),
        Thursday = COALESCE(pb.Thursday, 'Not Available'),
        Friday = COALESCE(pb.Friday, 'Not Available'),
        t.Notes
FROM    Teachers t
        LEFT JOIN PivotedBookings pb
            ON pb.TeacherID = t.ID
        LEFT JOIN TeacherBands tb
            ON tb.ID = t.Band;

减少 SQL Fiddle 上的示例


附录

读完这一行:

WHEN bd.DayText = 'Thursday' AND bd.BookingDuration = 2 or (bd.BookingDuration = 1 and bd.BookingDuration = 0)

这让我相信全天有 2 种可能性,要么是预订时间为 2,要么是表中同一教师和日期的上午和下午条目。在这种情况下,需要对数据进行两次透视,因此您的第一个 CTE 变为:

WITH Bookings AS
(   SELECT  BookingDays.TeacherID,
            [WeekDay] = DATENAME(WEEKDAY, BookingDate),
            [Status] = CASE WHEN [2] > 0 THEN 'Full Day'
                            WHEN [0] > 0 AND [1] > 0 THEN 'xxx'
                            WHEN [0] > 0 THEN 'PM'
                            WHEN [1] > 0 THEN 'AM'
                        END

    FROM    (   SELECT  TeacherID, BookingDate, BookingDuration, [X] = 1
                FROM    BookingDays
            ) BookingDays
            PIVOT
            (   SUM(X)
                FOR BookingDuration IN ([0], [1], [2])
            ) pvt
)

SQL Fiddle 上的更新示例(请注意周四老师 1)

于 2013-02-14T16:09:43.290 回答