MIN的替代选择,可以选择多行

时间:2013-02-14 15:17:39

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

以下SQL查询应该显示教师可用性。有3种可能的预订类型 - 上午,下午或全天。如果是AM预订,单元格中的文本应该显示PM,如果是PM预订,它应该显示AM,如果是全天预订,或者是AM和PM预订,它应该显示' xxx& #39;

这一切都可以在凌晨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

谢谢,马特

1 个答案:

答案 0 :(得分:4)

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

  • 0 - PM
  • 1 - AM
  • 2 - 全天

如果这不正确,你需要调整我的查询slighlty,但这应该让你走上正确的轨道。我还假设预订表中没有记录表示没有记录:

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;

<强> Cut down example on SQL Fiddle


<强>附录

读完这一行:

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

这让我相信全天有2种可能性,要么预订时间为2,要么是同一位教师的AM和PM条目以及表格中的日期。在这种情况下,需要将数据旋转两次,因此您的第一个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
)

<强> Updated example on SQL Fiddle (Note Thursday for Teacher 1)