2012-09-17 4 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  | 

Ceci est le résultat d'une requête que j'ai écrite. Il y a deux et plus de deux lignes avec le même ticketid. J'ai besoin de trouver le décalage horaire entre les deux premières dates dans chaque ticketidDifférence entre les dates dans deux lignes consécutives

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  | 

En conséquence;

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

Pouvez-vous me dire comment je peux faire cela?

Merci.

+1

Merci pour les données et résultats attendus. C'est génial si vous le montrez dans le formulaire 'INSERT', donc c'est facile à créer comme exemple, mais cela fonctionne. BTW, quelle version de PostgreSQL? –

Répondre

13

Pour PostgreSQL, je pense que vous voulez que le lag window function compare les lignes; ce sera beaucoup plus efficace qu'une auto-jointure et un filtre. Cela ne fonctionnera pas avec MySQL, car il ne semble toujours pas supporter les fonctions standard de la fenêtre SQL: 2003; voir ci-dessous.

Pour que les deux plus bas, vous pouvez utiliser la fonction de fenêtre dense_rank sur la ticketid, puis filtrer les résultats pour retourner uniquement les lignes où dense_rank() = 2, soit rangée avec le deuxième de-bas horodatage, où lag() produira la ligne avec l'horodatage le plus bas.

Voir this SQLFiddle qui montre l'exemple DDL et la sortie.

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; 

Je l'ai utilisé ticketdate comme le nom de la colonne de date parce date est un nom terrible pour une colonne (c'est un nom de type de données) et ne doit jamais être utilisé; il doit être cité en double dans de nombreuses situations pour fonctionner.

L'approche portable est probablement l'auto-joint que d'autres ont posté. L'approche de la fonction fenêtre ci-dessus fonctionne probablement aussi sur Oracle, mais ne semble pas dans MySQL. Autant que je sache, il ne supporte pas les fonctions de la fenêtre SQL: 2003.

La définition de schéma fonctionnera avec MySQL si vous SET sql_mode = 'ANSI' et utilisez timestamp au lieu de timestamp with time zone. Il semble que les fonctions de la fenêtre ne le seront pas; MySQL s'étrangle sur la clause OVER. Voir 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

Je pense que cette approche est valide, cependant, elle retournera des lignes supplémentaires quand il y a plus de 2 des mêmes ticketids. Il comparerait ticket1 à ticket2, ticket2 à ticket3, mais aussi ticket1 à ticket3, ce qui n'est pas souhaité. –

+0

True, mais le SQL est fait en ce qui concerne les données du problème. Il est facilement modifiable pour prendre en considération les 1er et 2ème, ou 1er et dernier ou quoi que ce soit. C'est fait pour 2 :). –

1

Essayez cette requête -

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

Je reçois des résultats différents et je suis un peu confus. Pouvez-vous montrer votre schéma et vos exemples de données? Comparer: http://sqlfiddle.com/#!9/846e8/6 –

+0

J'ai utilisé des données de la question. – Devart

+0

Ah. Il existe deux exemples de jeux de données. J'ai utilisé le top, vous avez utilisé l'autre. Ceci explique cela. Mon erreur. BTW, vaut la peine de noter dans votre réponse que c'est seulement MySQL. –