2013-04-22 3 views
0

Ниже приведенный SQL-запрос должен показывать доступность учителя. Существует 4 возможных типа бронирования: AM, PM, Full Day и Hourly. Если есть бронирование AM, текст в ячейке должен показать PM, если есть заказ PM, он должен показать AM, если есть полный дневной заказ или оба AM и PM, он должен показать «xxx». Все это прекрасно работает.Объединение строк в мой запрос сводной таблицы

Теперь я перехожу к почасовым заказам. Можно с уверенностью предположить, что на каждый день будет только 2-х часовой заказ, 1 для AM (время начала < = 12pm) и 1 для PM (время окончания> 12 вечера), что означает, что мы должны показать «xxx». Однако я действительно изо всех сил стараюсь показать это.

WITH Bookings AS 
( SELECT TeacherID, 
      [WeekDay] = DATENAME(WEEKDAY, BookingDate), 
      [Status] = CASE 
          WHEN [3] > 1 THEN 'XXX' 
          WHEN ([0] > 0 AND [1] > 0) THEN 'XXX' 
          WHEN [2] > 0 THEN 'XXX'        
          WHEN [0] > 0 THEN 'PM' 
          WHEN [1] > 0 THEN 'AM' 
          WHEN [3] > 0 AND CONVERT(time(0), EndTime) <= CONVERT(time(0), '12:00:00') THEN 'PM' 
          WHEN [3] > 0 AND CONVERT(time(0), StartTime) >= CONVERT(time(0), '12:00:00') THEN 'AM' 
          WHEN [3] > 0 AND CONVERT(time(0), StartTime) <= CONVERT(time(0), '12:00:00') AND CONVERT(time(0), EndTime) >= CONVERT(time(0), '12:00:00') THEN 'XXX'       
         END 
    FROM ( SELECT TeacherID, BookingDate, BookingDuration, StartTime, EndTime, [x] = 1 
       FROM BookingDays where (Status = 0 or Status IS NULL) 
      ) BookingDays 
      PIVOT 
      ( SUM(x) 
       FOR BookingDuration IN ([0], [1], [2], [3]) 
      ) pvt 

      WHERE BookingDate >= DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 0) AND BookingDate <= DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 6) 

), PivotedBookings AS 
( SELECT * 
    FROM Bookings 
      PIVOT 
      ( MAX([Status]) 
       FOR [WeekDay] IN ([Monday], [Tuesday], [Wednesday], [Thursday], [Friday]) 
      ) pvt 

) 
SELECT ID,Firstname,Surname,Band,'£' + CONVERT(varchar(50),DefaultChargeRateDaily) + '/' + '£' + CONVERT(varchar(50), DefaultPayRateDaily) as 'BandRates',Telephone,Mobile,Teacher,TeacherAssistant,KeyStage,MAX(Monday) Monday,MAX(Tuesday) Tuesday,MAX(Wednesday) Wednesday,MAX(Thursday) Thursday,MAX(Friday) Friday, Notes 
    FROM (
SELECT t.ID, 
     t.Firstname, 
     t.Surname, 
     tb.Band, 
     t.DefaultChargeRateDaily, 
     t.DefaultPayRateDaily, 
     t.Telephone, 
     t.Mobile, 
     t.Teacher, 
     t.TeacherAssistant, 
     CASE WHEN t.Nursery > 0 THEN 'NUR' WHEN t.Reception > 0 THEN 'REC' WHEN t.Year1 > 0 THEN 'Y1' WHEN t.Year2 > 0 THEN 'Y2' WHEN t.Year3 > 0 THEN 'Y3' WHEN t.Year4 > 0 THEN 'Y4' WHEN t.Year5 > 0 THEN 'Y5' WHEN t.Year6 > 0 THEN 'Y6' WHEN t.Year7 > 0 THEN 'Y7' WHEN t.Year8 > 0 THEN 'Y8' WHEN t.Year9 > 0 THEN 'Y9' WHEN t.Year10 > 0 THEN 'Y10' WHEN t.Year11 > 0 THEN 'Y11' WHEN t.ALevel > 0 THEN 'ALevel' END + ' - ' + CASE WHEN t.ALevel > 0 THEN 'ALevel' WHEN t.Year11 > 0 THEN 'Y11' WHEN t.Year10 > 0 THEN 'Y10' WHEN t.Year9 > 0 THEN 'Y9' WHEN t.Year8 > 0 THEN 'Y7' WHEN t.Year6 > 0 THEN 'Y6' WHEN t.Year5 > 0 THEN 'Y6' WHEN t.Year4 > 0 THEN 'Y4' WHEN t.Year3 > 0 THEN 'Y3' WHEN t.Year2 > 0 THEN 'Y2' WHEN t.Year1 > 0 THEN 'Y1' WHEN t.Reception > 0 THEN 'REC' WHEN t.Nursery > 0 THEN 'NUR' ELSE '' END as 'KeyStage', 

     Monday = CASE WHEN an.Date = DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 0) AND an.TeacherID = t.ID THEN an.Text WHEN t.Status = 0 THEN 'XXX' ELSE COALESCE(pb.Monday, '') END, 
     Tuesday = CASE WHEN an.Date = DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 1) AND an.TeacherID = t.ID THEN an.Text WHEN t.Status = 0 THEN 'XXX' ELSE COALESCE(pb.Tuesday, '') END, 
     Wednesday = CASE WHEN an.Date = DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 2) AND an.TeacherID = t.ID THEN an.Text WHEN t.Status = 0 THEN 'XXX' ELSE COALESCE(pb.Wednesday, '') END, 
     Thursday = CASE WHEN an.Date = DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 3) AND an.TeacherID = t.ID THEN an.Text WHEN t.Status = 0 THEN 'XXX' ELSE COALESCE(pb.Thursday, '') END, 
     Friday = CASE WHEN an.Date = DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 4) AND an.TeacherID = t.ID THEN an.Text WHEN t.Status = 0 THEN 'XXX' ELSE COALESCE(pb.Friday, '') END, 
     Notes 
FROM Teachers t 

     LEFT JOIN PivotedBookings pb 
      ON pb.TeacherID = t.ID 
     LEFT JOIN TeacherBands tb 
      ON tb.ID = t.Band 
     LEFT JOIN AvailabilityNotes an 
      ON t.ID = an.TeacherID 
      WHERE t.Active = 0 and (t.Status = 1 or t.Status = 0) and t.PrimarySchool = 1 
      ) T1 
GROUP BY ID,Firstname,Surname,Telephone,Mobile,Teacher,TeacherAssistant,KeyStage,Notes,DefaultChargeRateDaily,DefaultPayRateDaily,Band 
ORDER BY Surname,Firstname asc 

Первая часть генерирует следующие -

SELECT TeacherID, 
      [WeekDay] = DATENAME(WEEKDAY, BookingDate), 
      [Status] = CASE 
          WHEN [3] > 1 THEN 'XXX' 
          WHEN ([0] > 0 AND [1] > 0) THEN 'XXX' 
          WHEN [2] > 0 THEN 'XXX'        
          WHEN [0] > 0 THEN 'PM' 
          WHEN [1] > 0 THEN 'AM' 
          WHEN [3] > 0 AND CONVERT(time(0), EndTime) <= CONVERT(time(0), '12:00:00') THEN 'PM' 
          WHEN [3] > 0 AND CONVERT(time(0), StartTime) >= CONVERT(time(0), '12:00:00') THEN 'AM' 
          WHEN [3] > 0 AND CONVERT(time(0), StartTime) <= CONVERT(time(0), '12:00:00') AND CONVERT(time(0), EndTime) >= CONVERT(time(0), '12:00:00') THEN 'XXX'       
         END 
    FROM ( SELECT TeacherID, BookingDate, BookingDuration, StartTime, EndTime, [x] = 1 
       FROM BookingDays where (Status = 0 or Status IS NULL) 
      ) BookingDays 
      PIVOT 
      ( SUM(x) 
       FOR BookingDuration IN ([0], [1], [2], [3]) 
      ) pvt 

      WHERE BookingDate >= DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 0) AND BookingDate <= DATEADD(ww, DATEDIFF(ww,0,'04/22/2013'), 6) 

Столбцы таблицы:

TeacherID | WeekDay | Status 
9386 Monday  PM 
9386 Tuesday  AM 
9386 Wednesday XXX 
9763 Monday  PM 
9763 Tuesday  AM 
9763 Wednesday XXX 
9927 Monday  PM 
9927 Tuesday  AM 
9927 Wednesday XXX 
10358 Monday  PM 
10358 Monday  AM 

Мы можем видеть здесь, последние 2 строки нужно слияния и показывать в столбце состояния как XXX ,

Пример показан на скриншоте ниже. Выделенный желтый, он показывает PM. Тем не менее, есть 2 почасовых бронирования (BookingDuration ID 3), один с 10:00 до 11:00 и еще с 14:00 до 15:00. Поэтому это должно показать XXX, а не PM/AM.

Screenshot

Я надеюсь, что это имеет смысл!

+0

Не совсем понятно, что вы пытаетесь сделать, можете ли вы отредактировать свое сообщение со структурами таблиц, образцами данных и затем желаемым результатом запроса? – Taryn

+0

Спасибо bluefeet. Я добавил скриншот просто потому, что на сегодняшний день у меня закончилось время. При необходимости образцы данных могут быть опубликованы завтра. Благодарю. – dynamicuser

ответ

1

Ваша проблема может быть прослежена до первого запроса:

FROM ( SELECT TeacherID, BookingDate, BookingDuration, StartTime, EndTime, [x] = 1 
      FROM BookingDays 
      WHERE (Status = 0 OR Status IS NULL) 
     ) BookingDays 
     PIVOT 
     ( SUM(x) 
      FOR BookingDuration IN ([0], [1], [2], [3]) 
     ) pvt 

Идея этого должна была получить выводе там, где был один ряд в день на одного преподавателя, с добавлением StartTime и EndTime к подзапрос это не гарантирует, что вы получите одну строку для каждого учителя в день, потому что две записи могут иметь разное время начала/окончания на ту же дату, чтобы обойти эту проблему, вы можете использовать:

| TeacherID | BookingDate | BookingDuration | StartTime | EndTime | 
|-----------+-------------+-----------------+-----------+---------| 
| 1  | 20130422 |  3  | 10:00 | 11:00 | 
| 1  | 20130422 |  3  | 13:00 | 14:00 | 

в КТР бронирования это вернет (Если вы добавили начало/время окончания, чтобы выбрать список, но удаление их не будет делать это один ряд):

| TeacherID | WeekDay | Status | StartTime | EndTime | 
|-----------+---------|--------+-----------+---------| 
| 1  | Monday | 'AM' | 10:00 | 11:00 | 
| 1  | Monday | 'PM' | 13:00 | 14:00 | 

Если вы использовали следующие

FROM ( SELECT TeacherID, 
        BookingDate, 
        BookingDuration, 
        StartTime = MIN(StartTime) OVER(PARTITION BY TeacherID, BookingDate), 
        EndTime = MIN(StartTime) OVER(PARTITION BY TeacherID, BookingDate) 
        [x] = 1 
      FROM BookingDays 
      WHERE (Status = 0 OR Status IS NULL) 
     ) BookingDays 
     PIVOT 
     ( SUM(x) 
      FOR BookingDuration IN ([0], [1], [2], [3]) 
     ) pvt 

Использование оконных функций можно обеспечить только то же самое время_запуск и EndTime будут возвращены в комбинации учителя/день вы получите:

| TeacherID | WeekDay | Status | StartTime | EndTime | 
|-----------+---------|--------+-----------+---------| 
| 1  | Monday | 'XXX' | 10:00 | 14:00 | 

вы бы тогда не нужно объединить строки позже в запросе.

Еще одно изменение вам нужно сделать, это изменить заявление СЛУЧАЯ в течение Status чуть-чуть, так что вы получите полный запрос как:

WITH Bookings AS 
( SELECT TeacherID, 
      [WeekDay] = DATENAME(WEEKDAY, BookingDate), 
      [Status] = CASE 
          WHEN ([0] > 0 AND [1] > 0) THEN 'XXX' 
          WHEN [2] > 0 THEN 'XXX'        
          WHEN [0] > 0 THEN 'PM' 
          WHEN [1] > 0 THEN 'AM' 
          WHEN [3] > 0 AND StartTime <= CONVERT(TIME, '12:00:00') AND EndTime >= CONVERT(TIME, '12:00:00') THEN 'XXX' 
          WHEN [3] > 0 AND EndTime <= CONVERT(TIME, '12:00:00') THEN 'PM' 
          WHEN [3] > 0 AND StartTime >= CONVERT(TIME, '12:00:00') THEN 'AM'       
         END 
    FROM ( SELECT TeacherID, 
         BookingDate, 
         BookingDuration, 
         StartTime = CAST(MIN(StartTime) OVER(PARTITION BY TeacherID, BookingDate, BookingDuration) AS TIME), 
         EndTime = CAST(MAX(EndTime) OVER(PARTITION BY TeacherID, BookingDate, BookingDuration) AS TIME), 
         [x] = 1 
       FROM BookingDays 
       WHERE (Status = 0 OR Status IS NULL) 
      ) BookingDays 
      PIVOT 
      ( SUM(x) 
       FOR BookingDuration IN ([0], [1], [2], [3]) 
      ) pvt 
) 

Все, что я сделал здесь удалить строку WHEN [3] > 1, на всякий случай может быть два почасовых слота, встречающихся в AM, или оба в PM (я знаю, вы сказали, что можно предположить, что этого не произойдет, но для полноты, которую я добавил), и я переместил следующую строку выше до:

WHEN [3] > 0 AND StartTime <= CONVERT(TIME, '12:00:00') AND EndTime >= CONVERT(TIME, '12:00:00') THEN 'XXX' 

Th должны быть все изменения, необходимые для получения данных в требуемом формате.

Example on SQL Fiddle (учитель Примечание 5)

EDIT

Как вы сказали, если есть почасовой слот утром и слот днем, или наоборот, выше не удастся. Я думаю, что если вы измените свой пример дела на ниже, это должно решить проблему.

 [Status] = CASE 
         WHEN ([0] > 0 AND [1] > 0) THEN 'XXX' 
         WHEN [2] > 0 THEN 'XXX'  
         WHEN [3] > 0 AND StartTime <= CONVERT(TIME, '12:00:00') AND EndTime >= CONVERT(TIME, '12:00:00') THEN 'XXX' 
         WHEN [3] > 0 AND StartTime <= CONVERT(TIME, '12:00:00') AND [1] > 0 THEN 'XXX'   
         WHEN [3] > 0 AND StartTime >= CONVERT(TIME, '12:00:00') AND [0] > 0 THEN 'XXX' 
         WHEN [0] > 0 THEN 'PM' 
         WHEN [1] > 0 THEN 'AM' 
         WHEN [3] > 0 AND EndTime <= CONVERT(TIME, '12:00:00') THEN 'PM' 
         WHEN [3] > 0 AND StartTime >= CONVERT(TIME, '12:00:00') THEN 'AM'       
        END 
+0

еще раз, гений! Еще раз спасибо! – dynamicuser