Mysql
 sql >> Database >  >> RDS >> Mysql

ordine sql complesso di

Immagino che "id risposta" sia 0 per gli articoli ed è il numero dell'articolo per i commenti. Se questo è il tuo design, dovrebbe funzionare:

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

AGGIUNTO: Grazie per le informazioni aggiuntive nel tuo commento. Mettere i risultati nell'ordine che desideri non è così facile, perché la prima chiave di ordinamento è la data_creata del post di avvio del thread. Questo non è nella riga dei dati, quindi è necessario un join. Ecco la mia migliore ipotesi basata sulle informazioni aggiuntive (che non sono ancora abbastanza complete da impedirmi di indovinare):

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;

Potrebbe essere necessario modificare la sintassi per postgre. L'ho testato in SQL Server.

Se questo continua a non fare quello che vuoi, sii specifico su come desideri che i dati vengano restituiti. Preferibilmente, dimmi l'ordine "id" che dovrei vedere per i dati nel tuo file di dump e anche spiegare la base di tale ordine. Ecco cosa ho fatto:

  1. Tutti i messaggi in un thread (thread =a messaggi e relativi commenti) devono essere raggruppati insieme.

  2. All'interno di un thread, metti il ​​messaggio in cima, seguito dai suoi commenti in ordine cronologico inverso. Il thread con la data/_data di creazione più recente dovrebbe essere il primo, quindi il thread con la seconda data di creazione più recente e così via. (I tuoi dati di esempio contenevano molti commenti con la stessa data_di creazione, quindi ho usato "id" come chiave dell'ordine secondario per i commenti all'interno di un thread.)

Nota: Il tuo dump indica che la data_creata viene aggiornata a CURRENT_TIMESTAMP se un post viene modificato. Se questa è una bacheca live, tieni presente che ciò potrebbe far sì che i commenti vengano datati prima il messaggio principale e significa che un thread rimarrà in primo piano se viene modificato frequentemente (anche senza alcuna modifica effettiva al suo testo). (Questo non è rilevante per la mia soluzione, ma ho pensato che valesse la pena notare.)

Poiché è richiesto un join, questa query sarà ora molto più lenta. Il mio consiglio:mantieni due colonne di data, "thread_last_modified" e "item_last_modified". Dovrai aggiungere aggiornamenti a cascata dagli avviatori di thread ai commenti, ma penso che ne valga la pena se non ci sono molti aggiornamenti, perché la query può essere molto più semplice. Non l'ho testato perché richiede diverse modifiche al tuo design:

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;

AGGIUNTO N. 2 :Se vuoi solo il thread contenente il commento con id ::thisOne, penso che tu possa aggiungere questa riga tra le clausole ON e ORDER BY (per la mia prima soluzione aggiunta, il join):

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

In teoria, questa ricerca dovrebbe essere valutata solo una volta per la query, ma se non lo è in pratica, potresti precalcolarla come ::thisOneThreadID e aggiungere

where parentfeed.id = ::thisOneThreadID

Per la seconda soluzione, supponendo di eseguire nuovamente il precalcolo, prova con

where coalesce(id,reply_id) = ::thisOneThreadID

A proposito, sospetto che entrambe le mie soluzioni uniranno i thread che sono stati modificati per l'ultima volta esattamente nello stesso momento...