2012-09-17 23 views
7
+----------+--------------+-------------------------+ 
| ticketid | ticketpostid |   date   | 
+----------+--------------+-------------------------+ 
| 1387935 |  3147808 | 2012-09-17 13:33:01  | 
| 1387935 |  3147812 | 2012-09-17 13:33:41  | 
| 1387938 |  3147818 | 2012-09-17 13:35:01  | 
| 1387938 |  3148068 | 2012-09-17 13:37:01  | 
| 1387938 |  3148323 | 2012-09-17 14:47:01  | 
| 1387939 |  3147820 | 2012-09-17 13:36:01  | 
| 1387939 |  3147834 | 2012-09-17 13:36:25  | 
| 1387939 |  3147851 | 2012-09-17 13:41:01  | 
| 1387939 |  3147968 | 2012-09-17 13:59:06  | 
| 1387939 |  3147996 | 2012-09-17 14:03:01  | 

Dies ist ein Ergebnis einer Abfrage, die ich geschrieben habe. Es gibt zwei und mehr als zwei Zeilen mit derselben ticketid. Ich muss den Zeitunterschied zwischen den ersten beiden Datum in jedem ticketid findenUnterschied zwischen Daten in zwei aufeinanderfolgenden Zeilen

Ex.

+----------+--------------+-------------------------+ 
| ticketid | ticketpostid |   date   | 
+----------+--------------+-------------------------+ 
| 1387935 |  3147808 | 2012-09-17 13:33:01  | 
| 1387935 |  3147812 | 2012-09-17 13:33:41  | 
| 1387938 |  3147818 | 2012-09-17 13:35:01  | 
| 1387938 |  3148068 | 2012-09-17 13:37:01  | 
| 1387939 |  3147820 | 2012-09-17 13:36:01  | 
| 1387939 |  3147834 | 2012-09-17 13:36:25  | 

Als Ergebnis;

+----------+--------------+ 
| ticketid |time diff(sec)| 
+----------+--------------+ 
| 1387935 |  40  | 
| 1387938 |  120  | 
| 1387939 |  24  | 

Können Sie mir sagen, wie ich das tun kann?

Danke.

+1

Dank für die Daten und erwartetes Ergebnis. Es ist großartig, wenn Sie dies im 'INSERT'-Formular anzeigen, so dass es einfach ist, ein Sample zu erstellen, aber das funktioniert. BTW, welche PostgreSQL-Version? –

Antwort

13

Für PostgreSQL, ich glaube, Sie die lag window function wollen die Zeilen vergleichen; Es ist viel effizienter als ein Self-Join und Filter. Dies funktioniert nicht mit MySQL, da es die standardmäßigen Fensterfunktionen von SQL: 2003 anscheinend nicht unterstützt; siehe unten.

nur zu finden, die beide niedrigsten können Sie die dense_rank Fensterfunktion über die ticketid verwenden, dann die Ergebnisse filtern, um nur Zeilen zurückgeben, wo dense_rank() = 2, dh mit dem Zeitstempel von niedrigsten zweiter Reihe, wo lag() die Reihe produzieren wird mit der niedrigste Zeitstempel

Siehe this SQLFiddle, die Beispiel DDL und Ausgabe zeigt.

SELECT ticketid, extract(epoch from tdiff) FROM (
    SELECT 
     ticketid, 
     ticketdate - lag(ticketdate) OVER (PARTITION BY ticketid ORDER BY ticketdate) AS tdiff, 
     dense_rank() OVER (PARTITION BY ticketid ORDER BY ticketdate) AS rank 
    FROM Table1 
    ORDER BY ticketid) x 
WHERE rank = 2; 

I ticketdate als Name für die Datumsspalte verwendet haben, weil date ein schrecklicher Name für eine Spalte ist (es ist ein Datentyp Name ist) und nie verwendet werden sollte; Es muss in vielen Situationen doppelt zitiert werden, um zu funktionieren.

Der portable Ansatz ist wahrscheinlich der Self-Join anderen geschrieben haben. Der obige Fensterfunktionsansatz funktioniert wahrscheinlich auch bei Oracle, scheint aber in MySQL nicht zu funktionieren. Soweit ich herausfinden kann, unterstützt es nicht die Fensterfunktionen von SQL: 2003.

Die Schemadefinition funktioniert mit MySQL, wenn Sie SET sql_mode = 'ANSI' verwenden und timestamp anstelle von timestamp with time zone verwenden. Es scheint, dass die Fensterfunktionen nicht funktionieren; MySQL drosselt die OVER-Klausel. Siehe this SQLFiddle.

1
select 
    ticketid 
    ,time_to_sec(timediff(t2.date, t1.date)) as timediff 
from table t1 
join table t2 on t1.ticketid=t2.ticketid and t1.ticketpostid<t2.ticketpostid 
+2

Ich denke, dass dieser Ansatz gültig ist, jedoch wird es zusätzliche Zeilen zurückgeben, wenn es mehr als 2 der gleichen ticketids gibt. Es würde Ticket1 mit Ticket2, Ticket2 mit Ticket3, aber auch Ticket1 mit Ticket3 vergleichen, was nicht erwünscht ist. –

+0

Das stimmt, aber die SQL ist in Bezug auf die Daten des Problems gemacht. Es wird leicht modifiziert, um 1. und 2. oder 1. und letztes oder was auch immer in Betracht zu ziehen. Es ist getan für 2 :). –

1

Diese Abfrage -

INSERT INTO ticket_post(ticketid, ticketpostid, date) VALUES 
(1387935, 3147808, '2012-09-17 13:33:01'), 
(1387935, 3147812, '2012-09-17 13:33:41'), 
(1387938, 3147818, '2012-09-17 13:35:01'), 
(1387938, 3148068, '2012-09-17 13:37:01'), 
(1387938, 3148323, '2012-09-17 14:47:01'), 
(1387939, 3147820, '2012-09-17 13:36:01'), 
(1387939, 3147834, '2012-09-17 13:36:25'), 
(1387939, 3147851, '2012-09-17 13:41:01'), 
(1387939, 3147968, '2012-09-17 13:59:06'), 
(1387939, 3147996, '2012-09-17 14:03:01'); 

SELECT 
    ticketid, 
    TIME_TO_SEC(TIMEDIFF((
    SELECT t.date FROM ticket_post t WHERE t.ticketid = t1.ticketid AND t.date > t1.date ORDER BY t.date LIMIT 1), 
    MIN(date) 
)) diff FROM ticket_post t1 
GROUP BY ticketid; 

+----------+------+ 
| ticketid | diff | 
+----------+------+ 
| 1387935 | 40 | 
| 1387938 | 120 | 
| 1387939 | 24 | 
+----------+------+ 
+0

Ich bekomme unterschiedliche Ergebnisse und bin ein wenig verwirrt. Können Sie Ihre Schema- und Beispieldaten anzeigen? Vergleichen Sie: http://sqlfiddle.com/#!9/846e8/6 –

+0

Ich verwendete Daten von Frage. – Devart

+0

Ah. Dort befinden sich zwei Beispieldatensätze. Ich habe das oberste benutzt, du hast das andere benutzt. Das erklärt es. Mein Fehler. BTW, erwähnenswert in Ihrer Antwort, dass es nur MySQL ist. –

Verwandte Themen