Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Komplexe SQL-Reihenfolge

Ich vermute, dass "Antwort-ID" 0 für Artikel und die Artikelnummer für Kommentare ist. Wenn das dein Design ist, sollte das funktionieren:

select * from yourTable
order by
  case when "reply id" = 0 then id else "reply id" end, id

HINZUGEFÜGT: Danke für die zusätzlichen Informationen in Ihrem Kommentar. Die Ergebnisse in die gewünschte Reihenfolge zu bringen ist nicht so einfach, da der erste Sortierschlüssel das Erstellungsdatum des Thread-Starter-Beitrags ist. Dies befindet sich nicht in der Datenzeile, daher benötigen Sie einen Join. Hier ist meine beste Vermutung basierend auf den zusätzlichen Informationen (die immer noch nicht vollständig genug sind, um mich davon abzuhalten, zu raten):

select
  f.id, f.user_id, f.type, f.reply_id, f.text, f.url, f.created_date,
  coalesce(parentfeed.created_date,f.created_date) as thread_date
from feed as f left outer join feed as parentfeed
on f.reply_id = parentfeed.id
order by
  thread_date desc,
  case when f.reply_id = 0 then 0 else 1 end,
  created_date desc, id;

Möglicherweise müssen Sie die Syntax für postgre anpassen. Ich habe dies in SQL Server getestet.

Wenn dies immer noch nicht Ihren Wünschen entspricht, geben Sie bitte genau an, wie Sie die Daten zurückerhalten möchten. Sagen Sie mir vorzugsweise die "id"-Reihenfolge, die ich für die Daten in Ihrer Dump-Datei sehen soll, und auch Erklären Sie die Grundlage für diese Anordnung. Folgendes habe ich getan:

  1. Alle Nachrichten in einem Thread (Thread =eine Nachricht und ihre Kommentare) sollten zusammen gruppiert werden.

  2. Platzieren Sie innerhalb eines Threads die Nachricht ganz oben, gefolgt von ihren Kommentaren in umgekehrter chronologischer Reihenfolge. Der Thread mit dem zuletzt erstellten/_Datum sollte an erster Stelle stehen, dann der Thread mit dem zweitletzten Erstellungsdatum und so weiter. (Ihre Beispieldaten hatten viele Kommentare mit demselben Erstellungsdatum, daher habe ich "id" als sekundären Ordnungsschlüssel für die Kommentare innerhalb eines Threads verwendet.)

Hinweis: Ihr Dump zeigt an, dass created_date auf CURRENT_TIMESTAMP aktualisiert wird, wenn ein Beitrag geändert wird. Wenn dies ein Live-Messageboard ist, beachten Sie, dass dies dazu führen kann, dass Kommentare vorher datiert werden die übergeordnete Nachricht, und es bedeutet, dass ein Thread im Vordergrund bleibt, wenn er häufig geändert wird (auch ohne tatsächliche Änderung an seinem Text). (Das ist für meine Lösung nicht relevant, aber ich fand es erwähnenswert.)

Da ein Join erforderlich ist, ist diese Abfrage jetzt viel langsamer. Mein Vorschlag:Pflegen Sie zwei Datumsspalten, "thread_last_modified" und "item_last_modified". Sie müssen Updates von Thread-Startern zu Kommentaren kaskadieren, aber ich denke, es lohnt sich, wenn es nicht viele Updates gibt, da die Abfrage viel einfacher sein kann. Ich habe dies nicht getestet, weil es mehrere Änderungen an Ihrem Design erfordert:

select
  id, user_id, type, reply_id, text, url, thread_last_modified, item_last_modified
from feed
order by
  thread_last_modified desc,
  case when f.reply_id = 0 then 0 else 1 end,
  item_last_modified desc, id;

HINZUGEFÜGT #2 :Wenn Sie nur den Thread wollen, der den Kommentar mit der ID ::thisOne enthält, können Sie meiner Meinung nach diese Zeile zwischen den Klauseln ON und ORDER BY hinzufügen (für meine erste hinzugefügte Lösung, den Join):

where parentfeed.id = (
  select coalesce(reply_id,id)
  from feed
  where id = ::thisOne
)

Theoretisch sollte diese Suche nur einmal für die Abfrage ausgewertet werden, aber wenn dies in der Praxis nicht der Fall ist, können Sie sie als ::thisOneThreadID vorberechnen und hinzufügen

where parentfeed.id = ::thisOneThreadID

Versuchen Sie für die zweite Lösung, unter der Annahme, dass Sie erneut vorberechnen,

where coalesce(id,reply_id) = ::thisOneThreadID

Übrigens vermute ich, dass meine beiden Lösungen Threads zusammenführen werden, die zuletzt zur exakt gleichen Zeit geändert wurden ...