7 Stimmen

komplexe sql-ordnung nach

id    |    message    |    reply id    |    date  

1     |  my new app.. |     0          | 10 / 10 / 2009 (latest message on top, follow by replies)
5     | love ur app.. |     1          | 11 / 10 / 2009 (this should show under the main message)
6     | another comm  |     1          | 12 / 10 / 2009
2     | application 2 |     0          | 09 / 10 / 2009
3     | reply of 2    |     2          | 11 / 10 / 2009

Ich möchte die neuesten Kommentare und ihre Antworten nach den Hauptkommentaren anzeigen. Offensichtlich werden die Antworten das neueste Datum haben, also kann ich sie nicht nach Datum sortieren, weil die Antworten über den Hauptkommentaren stehen werden. Ich bin mir nicht sicher, wie ich das mit einer Abfrage richtig machen kann. Jede Idee ist bitte.

Datenbank-Dump: http://pastie.org/576963

8voto

Steve Kass Punkte 6896

Ich vermute, dass "reply id" bei Artikeln 0 und bei Kommentaren die Artikelnummer ist. Wenn das Ihr Design ist, sollte das funktionieren:

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

HINZUFÜGEN: Vielen Dank für die zusätzlichen Informationen in Ihrem Kommentar. Die Ergebnisse in die von Ihnen gewünschte Reihenfolge zu bringen, ist nicht so einfach, da der erste Ordnungsschlüssel das created_date des Thread-Startposts ist. Dieser steht nicht in der Datenzeile, so dass Sie einen Join benötigen. Hier ist meine beste Vermutung auf der Grundlage der zusätzlichen Informationen (die immer noch nicht vollständig genug sind, um mich vom Raten abzuhalten):

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 Sie damit immer noch nicht das erreichen, was Sie wollen, geben Sie bitte genau an, wie Sie die Daten zurückhaben wollen. Nennen Sie mir vorzugsweise die "id"-Reihenfolge, die ich für die Daten in Ihrer Dump-Datei sehen soll, und auch die Grundlage für diese Anordnung zu erläutern. Ich habe Folgendes getan:

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

  2. Innerhalb eines Themas steht die Nachricht an erster Stelle, gefolgt von den Kommentaren in umgekehrter chronologischer Reihenfolge. Das Thema mit dem jüngsten Erstellungsdatum sollte an erster Stelle stehen, dann das Thema mit dem zweitjüngsten Erstellungsdatum und so weiter. (Ihre Beispieldaten enthielten viele Kommentare mit demselben Erstellungsdatum, daher habe ich "id" als sekundären Ordnungsschlüssel für die Kommentare innerhalb eines Threads verwendet).

Nota: Ihr Dump zeigt, dass created_date auf CURRENT_TIMESTAMP aktualisiert wird, wenn ein Beitrag geändert wird. Wenn es sich um ein lebendes Forum handelt, sollten Sie sich bewusst sein, dass dies dazu führen kann, dass Kommentare datiert werden vor Das bedeutet, dass ein Thema an erster Stelle bleibt, wenn es häufig geändert wird (auch wenn sich der Text nicht ändert). (Das ist für meine Lösung nicht relevant, aber ich dachte, es sei erwähnenswert).

Da eine Verknüpfung erforderlich ist, wird diese Abfrage nun viel langsamer sein. Mein Vorschlag: Führen Sie zwei Datumsspalten, "thread_last_modified" und "item_last_modified". Sie müssen die Aktualisierungen von den Thread-Startern zu den Kommentaren kaskadieren, aber ich denke, es lohnt sich, wenn es nicht viele Aktualisierungen gibt, weil die Abfrage viel einfacher sein kann. Ich habe dies nicht getestet, weil es einige Ä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;

ZUSÄTZLICH #2 : Wenn Sie nur den Thread wollen, der den Kommentar mit der ID ::thisOne enthält, können Sie diese Zeile zwischen die ON- und ORDER BY-Klauseln einfügen (für meine erste zusätzliche Lösung, die Verknüpfung):

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

Theoretisch sollte dieser Lookup nur einmal für die Abfrage ausgewertet werden, aber wenn das in der Praxis nicht der Fall ist, könnte man ihn als ::thisOneThreadID vorberechnen und hinzufügen

where parentfeed.id = ::thisOneThreadID

Für die zweite Lösung, vorausgesetzt, Sie rechnen wieder vor, versuchen Sie

where coalesce(id,reply_id) = ::thisOneThreadID

Übrigens vermute ich, dass beide meiner Lösungen Threads zusammenführen, die genau zur gleichen Zeit zuletzt geändert wurden...

2voto

tpdi Punkte 33618

.... order by (irgendein Prädikat, das auf "Hauptkommentare" zutrifft, aber nicht auf Folgekommentare) desc, date desc

Da Sie nicht deutlich machen, was einen "Hauptkommentar" ausmacht, kann ich Ihnen nur das sagen. Wenn, wie in Ihrem Beispiel, alle Hauptkommentare ein reply_id von Null, könnte dies sein:

order by case reply_id = 0 then 1 else 0 end desc, date desc

Beachten Sie, dass die Verwendung der case-Anweisung anstelle einer einfachen Reihenfolge nach reply_id ist notwendig, weil der erste Ausdruck für alle Nicht-Hauptnachrichten denselben Wert (nämlich Null) haben soll, so dass sie ausschließlich nach dem zweiten Ausdruck sortiert werden, date .

(Oh, wenn ich Ihr Schema richtig verstehe, reply_id sollte eigentlich heißen in_repky_to_id .)

0voto

mson Punkte 7684

Ich bin mir über Ihre Anforderungen nicht sicher, daher ist meine Antwort eine Abstraktion... der Maximalwert - muss möglicherweise ein Minimalwert sein (auch hier bin ich mir über Ihre genauen Anforderungen nicht im Klaren)

select
    y.column1
    , y.column2
    , y.column3
    , y.datecolumn
from
(select 
    column1
    , max(datecolumn) as rank_date
 from tableA
 group by column1) as x
inner join tableA y on x.id = y.id
order by x.rank_date, y...., y.... desc, y... asc, etc...

Wenn Sie Sql-Server verwenden, gibt es eine Funktion namens over row_number, die Sie ebenfalls verwenden können.

0voto

txyoji Punkte 6490

Hier ist ein Link zur Darstellung hierarchischer Daten in einer relationalen Datenbank. http://dev.mysql.com/tech-resources/articles/hierarchical-data.html

Das Wesentliche ist, dass Sie sich am Tisch für so viele Stufen anmelden müssen, wie Sie tief gehen wollen. Die bereitgestellten Beispieldaten waren nur zwei Ebenen tief.

SELECT
f1.id AS `parent_id`, 
f1.text AS `parent_text`, 
f1.created_date AS `parent_created_date`, 
f2.*
FROM 
feed AS `f1`
LEFT JOIN feed `f2` ON (f1.id = f2.reply_id)
WHERE f1.reply_id = 0
ORDER BY f1.created_date DESC, f2.created_date DESC
;

Die Informationen zum übergeordneten Artikel werden in den Spalten f1.* und die Informationen zu den untergeordneten Artikeln (Antworten) in den Spalten f2.* gespeichert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X