funzione di aggregazione con la data sul Postgres
-
19-09-2019 - |
Domanda
Sono un po 'arrugginito sul mio SQL, forse si può darmi una mano su questa query.
Ho questi due tavoli per un sistema di biglietti (sto omettendo alcuni campi):
biglietti tabella
id - bigint
subject - text
user_id - bigint
closed - boolean
first_message - bigint
(chiave esterna, per l'ID della prossima tabella)
last_message - bigint
(come prima)
Tavolo ticket_messages
creation_date
Ho bisogno di interrogare i biglietti chiusi, e fare una media del tempo trascorso tra la prima creation_date messaggio e l'ultimo messaggio creation_date. Questo è quello che ho fatto finora:
SELECT t.id, t.subject, tm.creation_date
FROM tickets AS t
INNER JOIN ticket_messages AS tm
ON tm.id = t.first_message
OR tm.id = t.last_message
WHERE t.closed = true
Sto cercando qualche gruppo da o funzione di aggregazione per ottenere tutti i dati dalla tabella, e cercare di calcolare il tempo trascorso tra l'ultima e la prima, anche cercando di visualizzare le date per il primo e l'ultimo messaggio.
Aggiorna Ho aggiunto un inner join con la seconda tabella, invece di "O", ora ho entrambe le date, e posso trovare la somma dalla mia applicazione:
SELECT t.id, t.subject, tm.creation_date, tm2.creation_date
FROM tickets AS t
INNER JOIN ticket_messages AS tm
ON tm.id = t.first_message
INNER JOIN ticket_messages as tm2
ON tm2.id = t.last_message
WHERE t.closed = true
Credo che lo ha fatto ...
Soluzione
Qualcosa del genere dovrebbe fare per ottenere il nr di giorni trascorsi. Potrebbe essere necessario mettere questo in una sottoquery per tirare facilmente fuori più campi da 'biglietti'.
SELECT t.id,AVG(tlast.creation_date - tfirst.creation_date)
FROM tickets AS t
INNER JOIN ticket_messages AS tfirst
ON tm.id = t.first_message
INNER JOIN ticket_messages AS tlast
ON tm.id = t.last_message
WHERE t.closed = true
GROUP BY t.id
Il che potrebbe portare a (non testato ..) esempio
select t.id,t.subject,sub.nr_days
FROM (
SELECT t.id,AVG(tlast.creation_date - tfirst.creation_date) as nr_days
FROM tickets AS t
INNER JOIN ticket_messages AS tfirst
ON tm.id = t.first_message
INNER JOIN ticket_messages AS tlast
ON tm.id = t.last_message
WHERE t.closed = true
GROUP BY t.id ) AS sub
INNER JOIN tickets AS t
ON sub.id = t.id;
Altri suggerimenti
Si sta tentando di combinare due query in una e cercando di ottenere i dati da tre righe di dati da due tabelle. Entrambi hanno bisogno di essere fissato.
Prima di tutto, non si dovrebbe tentare di mescolare i dati aggregati (ad esempio le medie) con i dettagli per singole voci - è necessario query separate per questo. possono farlo, ma l'uscita è ripetitivo e quindi sprechi (tutti i singoli elementi in un gruppo avranno gli stessi dati aggregati).
In secondo luogo, è necessario trovare il primo messaggio e l'ultimo messaggio per un dato biglietto. Quindi, tale query è:
SELECT t.id, t.subject, tm1.creation_date as start, tm2.creation_date as end,
tm2.creation_date - tm1.creation_date as close_interval
FROM tickets AS t
INNER JOIN ticket_messages AS tm1 ON t.last_message = tm1.id
INNER JOIN ticket_messages AS tm2 ON t.last_message = tm2.id
WHERE t.closed = true
Questo ti dà tre righe di dati per ogni riga del risultato - come richiesto. Il valore calcolato dovrebbe essere un tipo di intervallo - supponendo che PostgreSQL ha effettivamente quel tipo. (In Informix, il tipo potrebbe effettivamente essere INTERVAL DAY (n) per un adeguato n, ad esempio 9).
È possibile mediare quegli intervalli, ora. È possibile non date la media perché le date non possono essere sommati e non possono essere divisi; media coinvolge sia di somma e la divisione. Gli intervalli possono essere aggiunte e divise.