Alternative à MIN pour sélectionner plus d'une rangée

La requête SQL ci-dessous est supposée montrer une disponibilité des enseignants. Il existe 3 types de réservation possibles: AM, PM ou Full Day. S'il y a une réservation AM, le text dans la cellule devrait indiquer PM, s'il y a une réservation PM, il devrait montrer AM, s'il y a une réservation d'une journée, ou une réservation AM et PM, il devrait afficher 'xxx'.

Tout cela fonctionne très bien quand il y a 1h du matin, 13h ou 1 journée complète, mais s'il y a 1h du matin et 13h le même jour, il n'y aura pas de XXX parce que j'utilise le MIN (). Comment puis-je l'get pour évaluer toutes les réservations en un jour, plutôt que le plus petit? (Vous pouvez voir que j'ai essayé de montrer ce que je veux dire dans la section du code du jeudi.

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 

Colonnes de table:

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

Merci, Matt

Je pense que le problème est que vous essayez d'effectuer 2 opérations en même time qui doivent être séparées (vérifiez le jour de la semaine et vérifiez la durée de la réservation). Pour ce faire j'ai assumé votre réservation Durées à être:

  • 0 – PM
  • 1 – AM
  • 2 – Journée complète

Si ce n'est pas correct, vous aurez besoin de modifier ma requête slighlty, mais cela devrait vous mettre sur la bonne voie. J'ai également supposé aucun logging dans la table de réservation signifie pas disponible:

 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; 

Réduire l'exemple sur SQL Fiddle


ADDENDA

Ayant lu cette ligne:

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

Cela m'amène à croire qu'il y a 2 possibilités pour une journée complète, soit une durée de 2 heures, ou une input AM et PM pour le même professeur et la même date dans le tableau. Dans ce cas, il est nécessaire de faire pivoter datatables deux fois, de sorte que votre premier CTE devienne:

 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 ) 

Exemple mis à jour sur SQL Fiddle (Note Thursday for Teacher 1)