2014-06-16 10 views
6

Sorry für den vageen Titel (ich weiß nur nicht, wie dieses Rätsel beschreiben)Gruppe aufeinanderfolgenden Reihen von gleichem Wert mit der Zeit umspannen

Geben Sie die folgende Tabelle für ein Klassenzimmer:

╔═══════════╦════════════╦═══════════╦═══════════╦═════════╗ 
║ Classroom ║ CourseName ║ Lesson ║ StartTime ║ EndTime ║ 
╠═══════════╬════════════╬═══════════╬═══════════╬═════════╣ 
║  1001 ║ Course 1 ║ Lesson 1 ║  0800 ║ 0900 ║ 
║  1001 ║ Course 1 ║ Lesson 2 ║  0900 ║ 1000 ║ 
║  1001 ║ Course 1 ║ Lesson 3 ║  1000 ║ 1100 ║ 
║  1001 ║ Course 2 ║ Lesson 10 ║  1100 ║ 1200 ║ 
║  1001 ║ Course 2 ║ Lesson 11 ║  1200 ║ 1300 ║ 
║  1001 ║ Course 1 ║ Lesson 4 ║  1300 ║ 1400 ║ 
║  1001 ║ Course 1 ║ Lesson 5 ║  1400 ║ 1500 ║ 
╚═══════════╩════════════╩═══════════╩═══════════╩═════════╝ 

ich mag die Tabelle der Gruppe diese anzuzeigen: an einem Zeitplan

╔═══════════╦════════════╦═══════════╦═════════╗ 
║ Classroom ║ CourseName ║ StartTime ║ EndTime ║ 
╠═══════════╬════════════╬═══════════╬═════════╣ 
║  1001 ║ Course 1 ║  0800 ║ 1100 ║ 
║  1001 ║ Course 2 ║  1100 ║ 1300 ║ 
║  1001 ║ Course 1 ║  1300 ║ 1500 ║ 
╚═══════════╩════════════╩═══════════╩═════════╝ 

Grundsätzlich suchen wir, die zeigen, welche crouse verwenden welches Klassenzimmer während einer bestimmten Zeitspanne ...

Mein erster Gedanke war: Gruppe von Classroom und CourseName und Max und Min für start\end Zeit dauern, aber das gibt mir nicht die Zeit reicht es wird zeigen, als ob Kurs 1 ist mit den Classroom von 08:00 - 16: 00 ohne Pause in der Mitte.

+0

Ich weiß nicht, ob es Ihnen helfen kann, aber versuchen Sie Folgendes: http://dba.stackexchange.com/questions/31281/count-consecutive-rows-in-mysql Wahrscheinlich ist es viel einfacher, wenn Tun Sie dies in der Sprache, in der Sie die Datenbank verwenden. (Wenn Sie verwenden) –

+0

habe ich nicht wirklich versucht, aber was ist, wenn Sie row_number um eine eindeutige Nummer für jede aufeinanderfolgende Gruppe (Sie können nach Datum bestellen) bekommen. Sobald Sie dies getan haben, sollten Sie in der Lage sein, die Gruppe wie oben beschrieben durchzuführen. – Andrew

Antwort

6

Die Abfrage bestimmt jede Reihe EndTime von NOT EXISTS mit keiner anderen Klasse oder Kurs eines anderen Typs, um sicherzustellen, zwischen einem Kurs Bereich des StartTime und EndTime geplant ist und verwendet dann MIN und GROUP BY die StartTime zu finden.

Der NOT EXISTS Teil stellt sicher, dass es nicht „Pausen“ zwischen den StartTime und EndTime Bereiche durch für alle Zeilen zu suchen, die eine EndTime zwischen StartTime und EndTime haben aber gehören zu einer anderen CourseName oder CourseRoom.

SELECT  
    t0.ClassRoom, 
    t0.CourseName, 
    MIN(t0.StartTime), 
    t0.EndTime 
FROM (
    SELECT 
    t1.ClassRoom, 
    t1.CourseName, 
    t1.StartTime, 
    (
     SELECT MAX(t2.EndTime) 
     FROM tableA t2 
     WHERE t2.CourseName = t1.CourseName 
     AND t2.ClassRoom = t1.ClassRoom 
     AND NOT EXISTS (SELECT 1 FROM tableA t3 
      WHERE t3.EndTime < t2.EndTime 
      AND t3.EndTime > t1.EndTime 
      AND (t3.CourseName <> t2.CourseName 
      OR t3.ClassRoom <> t2.ClassRoom) 
     ) 
    ) EndTime 
    FROM tableA t1 
) t0 GROUP BY t0.ClassRoom, t0.CourseName, t0.EndTime 

http://www.sqlfiddle.com/#!6/39d4b/9

+0

Okay, damit funktioniert .. danke .. aber ich habe Schwierigkeiten, den letzten Teil zu verstehen, wo es NICHT EXISIERT steht .... kannst du es über die Logik ausarbeiten? – Mortalus

+0

@Mortalus siehe Update – FuzzyTree

+0

brillante Lösung ... +1 für das –

3

Wenn Sie mit SQL Server 2012 oder besser können Sie LAG verwenden Sie den vorherigen Wert einer Spalte zu bekommen, dann SUM() OVER (ORDER BY ...) eine rollende Summe zu erstellen, in diesem Fall ein, dass die Änderung zählen das kann der course werden, da die GROUP BY Anker verwendet

With A AS (
    SELECT ClassRoom 
     , CourseName 
     , StartTime 
     , EndTime 
     , PrevCourse = LAG(CourseName, 1, CourseName) OVER (ORDER BY StartTime) 
    FROM Table1 
), B AS (
    SELECT ClassRoom 
     , CourseName 
     , StartTime 
     , EndTime 
     , Ranker = SUM(CASE WHEN CourseName = PrevCourse THEN 0 ELSE 1 END) 
       OVER (ORDER BY StartTime, CourseName) 
    FROM A 
) 
SELECT ClassRoom 
    , CourseName 
    , MIN(StartTime) StartTime 
    , MAX(EndTime) EndTime 
FROM B 
GROUP BY ClassRoom, CourseName, Ranker 
ORDER BY StartTime 

SQLFiddle demo

+0

Große Antwort! Kluge Verwendung der 'SUM()' Funktion.Ich musste Ihre Anfrage an mein Problem anpassen, indem ich 'partition by ClassRoom' zu der Klausel' OVER() 'in den Funktionen' LAG() 'und' SUM() 'hinzufügte, um mehrere Klassenräume handhaben zu können. Vielen Dank. –

0
 CREATE TABLE Classroom(Classroom VARCHAR(100), CourseName VARCHAR(100), Lesson VARCHAR(100), StartTime VARCHAR(100), EndTime VARCHAR(100)) 
INSERT INTO Classroom 
SELECT '1001','Course 1','Lesson 1 ','0800','0900' 
UNION SELECT '1001','Course 1','Lesson 2 ','0900','1000' 
UNION SELECT '1001','Course 1','Lesson 3 ','1000','1100' 
UNION SELECT '1001','Course 2','Lesson 10','1100','1200' 
UNION SELECT '1001','Course 2','Lesson 11','1200','1300' 
UNION SELECT '1001','Course 1','Lesson 4 ','1300','1400' 
UNION SELECT '1001','Course 1','Lesson 5 ','1400','1500' 

SELECT * FROM Classroom 

;WITH CTE_ClassRooms AS (
SELECT *,ROW_NUMBER() over(partition by classroom,CourseName order by StartTime) AS R FROM Classroom A 
WHERE NOT EXISTS(SELECT 1 FROM Classroom B WHERE B.Classroom = A.Classroom AND B.CourseName = A.CourseName AND B.StartTime = A.EndTime) 
UNION ALL 
SELECT B.*,R fROM CTE_ClassRooms A JOIN Classroom B ON B.Classroom = A.Classroom AND B.CourseName = A.CourseName AND A.StartTime = B.EndTime 
) 

--SELECT * FROM CTE_ClassRooms order by Classroom,CourseName,R 

SELECT Classroom,CourseName,MIN(StartTime),MAX(EndTime) 
FROM CTE_ClassRooms 
GROUP BY Classroom,CourseName,R 
+0

Willkommen bei Stack Overflow, versuchen Sie bitte, einige zusätzliche Informationen anstelle von nur einer Abfrage bereitzustellen. – Marcel

Verwandte Themen