sql >> Database >  >> RDS >> Mysql

complexe sql-bestelling door

Ik vermoed dat "antwoord-ID" 0 is voor artikelen en het artikelnummer voor opmerkingen. Als dat jouw ontwerp is, zou dit moeten werken:

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

TOEGEVOEGD: Bedankt voor de aanvullende informatie in je reactie. Het is niet zo eenvoudig om de resultaten in de gewenste volgorde te plaatsen, omdat de eerste bestelsleutel de aangemaakte_datum van de threadstarterpost is. Dit staat niet in de datarij, dus je hebt een join nodig. Hier is mijn beste schatting op basis van de aanvullende informatie (die nog steeds niet volledig genoeg is om te voorkomen dat ik gok):

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;

Mogelijk moet u de syntaxis voor postgre aanpassen. Ik heb dit getest in SQL Server.

Als dit nog steeds niet doet wat je wilt, geef dan specifiek aan hoe je de gegevens terug wilt. Vertel me bij voorkeur de "id"-volgorde die ik moet zien voor de gegevens in je dumpbestand, en ook leg de basis voor die bestelling uit. Dit is wat ik deed:

  1. Alle berichten in een thread (thread =a messages and its comments) moeten gegroepeerd worden.

  2. Plaats binnen een thread het bericht bovenaan, gevolgd door de opmerkingen in omgekeerde chronologische volgorde. De thread met de meest recent aangemaakte/_datum moet eerst zijn, dan de thread met de op een na meest recente aangemaakte_datum, enzovoort. (Uw voorbeeldgegevens bevatten veel opmerkingen met dezelfde create_date, dus ik gebruikte "id" als secundaire volgordesleutel voor de opmerkingen in een thread.)

Opmerking: Je dump geeft aan dat created_date wordt bijgewerkt naar CURRENT_TIMESTAMP als een bericht wordt gewijzigd. Als dit een live prikbord is, houd er dan rekening mee dat opmerkingen hierdoor vóór kunnen worden gedateerd het bovenliggende bericht, en het betekent dat een thread bovenaan blijft staan ​​als deze vaak wordt gewijzigd (zelfs zonder daadwerkelijke wijziging in de tekst). (Dat is niet relevant voor mijn oplossing, maar ik vond het het vermelden waard.)

Omdat een join vereist is, zal deze query nu veel langzamer zijn. Mijn suggestie:behoud twee datumkolommen, "thread_last_modified" en "item_last_modified". Je zult updates van thread-starters naar opmerkingen moeten cascaderen, maar ik denk dat het de moeite waard is als er niet veel updates zijn, omdat de vraag veel eenvoudiger kan zijn. Ik heb dit niet getest omdat er verschillende wijzigingen in je ontwerp nodig zijn:

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;

TOEGEVOEGD #2 :Als je alleen de thread wilt met de opmerking met id ::thisOne, denk ik dat je deze regel tussen de ON- en ORDER BY-clausules kunt toevoegen (voor mijn eerste toegevoegde oplossing, de join):

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

In theorie zou deze zoekopdracht slechts één keer moeten worden geëvalueerd voor de zoekopdracht, maar als dit in de praktijk niet het geval is, kunt u deze vooraf berekenen als ::thisOneThreadID en toevoegen

where parentfeed.id = ::thisOneThreadID

Probeer voor de tweede oplossing, ervan uitgaande dat u opnieuw pre-berekent,

where coalesce(id,reply_id) = ::thisOneThreadID

Trouwens, ik vermoed dat mijn beide oplossingen threads zullen samenvoegen die het laatst op exact hetzelfde moment zijn gewijzigd...



  1. Kopieer gegevens naar een nieuwe tabel in MySQL

  2. HTML opslaan in MySQL:blob of tekst?

  3. SQL Server-back-upcontrole

  4. Een berichtensysteem in DB maken (vooral MySQL)