2016-05-21 10 views
1

Ich habe eine Ereignistabelle mit starting_date und ending_date. Ich möchte die sortieren sie wie folgt:Komplexe Sortierreihenfolge nach Anfangs- und Enddatum auf MySQL

Es gibt 3 Gruppen von Zeilen und sie sollten nacheinander erscheinen, jede Gruppe mit seiner Reihenfolge. Die Gruppen sind wie folgt:

  • Gruppe 1: starting_date = curdate() and ending_date = curdate(). Die Zeilen sollten nach id asc geordnet werden.

  • Gruppe 2: starting_date <= curdate() and ending_date > curdate(). It's Elemente sollten bestellt werden von ending_date asc

  • Gruppe 3: starting_date > curdate(). Es ist Elemente sollten durch starting date asc

Nimmt man heute may 21 ist bestellt werden, ist dies ein Beispiel für die Ausgabe ich brauche:

| id | starting_date | ending_date | 

// Group 1 
| 1 | may 21  | may 21 | 
| 2 | may 21  | may 21 | 

// Group 2 
| * | may 20  | may 23 | 
| * | may 15  | may 25 | 
| * | may 17  | may 26 | 
| * | may 21  | may 27 | 

// Group 3 
| * | may 23  | may 25 | 
| * | may 24  | may 25 | 

Wie Sie sehen können, jede Gruppe nacheinander angezeigt wird, und jede Zeile Innerhalb einer Gruppe wird durch die angegebenen order by bestellt.

Bisher habe ich versucht ORDER BY CASE WHEN Sätze verwenden, aber ich finde mich nicht in der Lage sollte zu verstehen, wenn ich:

  • Verwenden Sie mehrere CASE ... END Aussagen unter dem ORDER BY
  • Verwenden Sie mehrere WHEN ... THEN Anweisungen innerhalb eines ORDER BY CASE ... END
  • Beide, mehrere CASE mit mehreren when in jedem.
  • Dies kann nicht mit ORDER BY durchgeführt werden.

Dies ist eine der vielen SELECT Sätze, die ich versucht habe:

select events.id, events.starting_date, events.ending_date from events 
    where events.ending_date >= CURDATE() 
    order by 
     case 
      when (events.starting_date = curdate() and events.ending_date = (curdate() + interval 23 hour + interval 59 minute)) then 
      0 
      when (events.starting_date <= curdate() and events.ending_date > curdate()) then 
      1 
      when (events.starting_date > curdate()) then 
      2 
     end asc 

Diese Abfrage auf die richtige Gruppe setzen Reihen, aber sie sind nicht in ihrer jeweiligen Gruppe bestellt.

Dieser andere setzt die erste Gruppe am Ende.

order by 

    case when (events.starting_date = curdate() and events.ending_date = (curdate() + interval 23 hour + interval 59 minute)) then events.id end asc, 
    case when (events.starting_date <= curdate() and events.ending_date > curdate()) then events.ending_date end asc, 
    case when (events.starting_date > curdate()) then events.starting_date end asc 

Was mache ich falsch?

Antwort

1

Die Sortierlogik, die Sie zu kodieren versuchen, benötigt zwei Sortiervariablen. Die erste Art basiert darauf, zu welcher Gruppe (1-3) jeder Datensatz gehört. Die zweite Art findet innerhalb jeder Gruppe statt. Der richtige Ansatz besteht darin, die Logik der zwei Versuche zu verwenden, die Sie in Ihrer Frage gemacht haben. Die allgemeine Form der ORDER BY ist:

ORDER BY group_number, something_else 

wo die Gruppennummer 1, 2 oder 3, und das etwas anderes die spezifische Reihenfolge für diese Gruppe ist.Aber der Haken hier ist, dass group_number und something_else jeweils eine separate CASE Aussage haben. Im Fall von Gruppe 1 möchten Sie ORDER BY 1, events.id. Ich fügte auch eine ELSE-Bedingung zu den CASE-Ausdrücken hinzu, um Standardfälle zu behandeln, die nicht abgedeckt werden, und alle solche Datensätze werden in einer Gruppe am Ende der Ergebnismenge angezeigt, sortiert nach id.

SELECT events.id, events.starting_date, events.ending_date 
FROM events 
WHERE events.ending_date >= CURDATE() 
ORDER BY 
    (CASE 
     WHEN (events.starting_date = CURDATE() AND 
       events.ending_date = (CURDATE() + INTERVAL 23 HOUR + INTERVAL 59 MINUTE)) 
      THEN 1 
     WHEN (events.starting_date <= CURDATE() AND 
       events.ending_date > CURDATE()) 
      THEN 2 
     WHEN (events.starting_date > CURDATE()) 
      THEN 3 
     ELSE 4 
    END), 
    (CASE 
     WHEN (events.starting_date = CURDATE() AND 
       events.ending_date = (CURDATE() + INTERVAL 23 HOUR + INTERVAL 59 MINUTE)) 
      THEN events.id 
     WHEN (events.starting_date <= CURDATE() AND 
       events.ending_date > CURDATE()) 
      THEN events.ending_date 
     WHEN (events.starting_date > CURDATE()) 
      THEN events.starting_date 
     ELSE events.id 
    END) 
+1

Funktioniert wie ein Charme –

Verwandte Themen