2017-12-04 4 views
1

Okay, so habe ich eine Tabelle mit einer Spalte user_id und eine submited_dtm Spalte.SQL-wie zu ähnlichen Daten abrufen

Ich möchte Instanzen finden, in denen Benutzer mehrere Datensätze innerhalb von 1 Tag eingereicht und zählen, wie oft das passiert ist.

Ich habe versucht, so etwas wie

select * from table_t t where 
(select count(*) from table_t t2 where 
t.user_id = t2.user_id and 
t.pk!=t2.pk and 
t.submitted_dtm between t2.submitted_dtm-.5 and t2.submitted_dtm+.5)>0; 

Das Problem ist, dass diese Abfrage für jeden Datensatz in einem Datum Gruppe ein Ergebnis zurückgibt. Stattdessen möchte ich nur ein Ergebnis pro Datumsgruppe. Im Idealfall würde ich nur in dieser Gruppe zählen.

Das heißt, wenn ich 6 Datensätze:

user_id  submitted_dtm 
-------------------------- 
1   12/04/2017 1:15 
1   12/04/2017 5:50 
2   11/25/2017 2:00 
2   11/25/2017 3:25 
2   11/25/2017 6:05 
2   10/06/2017 4:00 

Ich möchte 2 Ergebnisse, eine Zählung von 2 und eine Zählung der 3.

Ist es möglich, dies in SQL zu tun?

+0

Dies kann in einfachen SQL erfolgen. Wie schwierig es ist, hängt jedoch von zwei Dingen ab. Einer ist einfach: Was ist Ihre Oracle-Datenbankversion? Wenn Sie nicht sicher sind, führen Sie 'select * from v $ version 'aus. Nein, überprüfe das; Führen Sie die Anweisung 'select' aus, auch wenn Sie sich sicher sind. Geben Sie die vollständige Versionsnummer ein (z. B. 12.1.0.2.0 statt "12c"). Die andere Sache ist die Bedeutung Ihres Problems. Was möchten Sie zählen, wenn der Benutzer an einem Tag um 15 Uhr etwas einreicht, und dann noch einmal fünf Mal im Abstand von sechs Stunden für insgesamt sechs Einsendungen? (Fortsetzung folgt) – mathguy

+1

Ist das ein Vorkommen? Oder wird das als "fünf" gezählt, weil es wirklich fünf Einreichungen gibt, denen innerhalb von weniger als 24 Stunden eine weitere Einreichung folgte? Oder sind es nur zwei - weil die erste Einreichung ein 24-Stunden-Fenster öffnet, sind die nächsten drei in diesem Fenster, aber die fünfte ist nicht, und es öffnet sich ein eigenes, neues Fenster? Alle drei Optionen (die sich auch bei den gleichen Eingaben sehr unterscheiden) sind für verschiedene Probleme gültig und sinnvoll. Also, bitte klären Sie. (Fortsetzung folgt) – mathguy

+1

Bitte erläutern Sie auch, was Sie mit "innerhalb von 1 Tag" meinen.Meinst du "am selben Kalendertag", oder kann das über Tagesgrenzen hinweg gehen und bedeutet stattdessen "innerhalb von 24 Stunden, unabhängig vom Kalenderdatum"? Und wenn ja, bedeutet "innerhalb von 24 Stunden" STRENG weniger als 24 Stunden oder GENAU 24 Stunden auch "innerhalb von 24 Stunden"? – mathguy

Antwort

3

Im Anschluss an Dessma Antwort auf.

select user_id, trunc(submitted_dtm), count(1) 
    from table_t 
group by user_id, trunc(submitted_dtm) 
having count(1) > 1; 

Sqlfiddle

+0

Mir war die Funktion trunc() nicht bekannt. Das funktioniert großartig! – DFL

1

Dies ist eine allgemeine Idee, wie Sie die Instanzen erhalten.

select user_id, t1.submitted_dtm t1submitted, t2.submitted_dtm t2submtted 
from table_t t1 join table_t t2 using (user_id) 
where t2.submitted_dtm > t1.submitted_dtm 
and t2.submitted_dtm - t1.submitted_dtm <= 1; 

Die letzte Zeile irgendwie könnte geändert je nachdem, was Sie von within a day bedeuten.

Um die Instanzen zu zählen, erstellen Sie eine abgeleitete Tabelle aus dem obigen und wählen Sie count (*) daraus aus.

+1

Sie nicht brauchen würden um sicherzustellen, dass t2submitted_dtm> t1 submited_dtm? – kfinity

+0

Wie geht das mit fünf oder sechs Einreichungen desselben Benutzers, alle innerhalb eines Tages voneinander? – mathguy

+0

FYI, für Oracle SQL wäre die Join-Syntax 'Join table_t t2 auf t1.user_id = t2.user_id' – kfinity

2

Ich habe keine Daten, die es zu testen, aber ich vermute, so etwas wie dies den Trick tun würde:

SELECT user_id,To_char(t.submitted_dtm, 'dd/mm/yyyy'), COUNT(*) 
    FROM table_t t 
INNER JOIN table_t t2 
    ON t.user_id = t2.user_id 
    AND t.pk != t2.pk 
    AND t.submitted_dtm BETWEEN t2.submitted_dtm - .5 AND 
     t2.submitted_dtm + .5 
GROUP BY user_id,To_char(t.submitted_dtm, 'dd/mm/yyyy') 
HAVING COUNT(*) > 1 
+1

Der gesamte innere T2-Join wird hier nicht benötigt, IMO. – kfinity

+0

kfinity Das ist absolut richtig, ich habe mich ziemlich in Gedanken verloren, als ich die Abfrage im Editor schrieb. SQL Fiddle sieht wie ein nettes Werkzeug aus, ich werde definitiv versuchen, das nächste Mal zu verwenden:) – Dessma

3

In Oracle 12.1 und höher, können Sie solche Probleme leicht mit der match_recognize Klausel lösen. Link zur Dokumentation (mit Beispielen) unten; Meine einzige Anmerkung zu der folgenden Lösung ist, dass ich das Datum im Datentyp DATE belassen habe, besonders wichtig, wenn die Ausgabe in weiteren Berechnungen verwendet wird. Wenn dies nicht der Fall ist, können Sie innerhalb von TO_CHAR() mit dem für Ihre Benutzer geeigneten Format modulieren.

https://docs.oracle.com/database/121/DWHSG/pattern.htm#DWHSG8956

with 
    inputs (user_id, submitted_dtm) as (
    select 1, to_date('12/04/2017 1:15', 'mm/dd/yyyy hh24:mi') from dual union all 
    select 1, to_date('12/04/2017 5:50', 'mm/dd/yyyy hh24:mi') from dual union all 
    select 2, to_date('11/25/2017 2:00', 'mm/dd/yyyy hh24:mi') from dual union all 
    select 2, to_date('11/25/2017 3:25', 'mm/dd/yyyy hh24:mi') from dual union all 
    select 2, to_date('11/25/2017 6:05', 'mm/dd/yyyy hh24:mi') from dual union all 
    select 2, to_date('10/06/2017 4:00', 'mm/dd/yyyy hh24:mi') from dual 
) 
-- End of simulated inputs (for testing only, not part of the solution). 
-- SQL query begins below this line. Use your actual table and column names. 
select user_id, submitted_dtm, cnt 
from inputs 
match_recognize(
    partition by user_id 
    order by  submitted_dtm 
    measures  trunc(a.submitted_dtm) as submitted_dtm, 
       count(*) as cnt 
    pattern  (a b+) 
    define  b as trunc(submitted_dtm) = trunc(a.submitted_dtm) 
); 

    USER_ID SUBMITTED_DTM    CNT 
---------- ------------------- ---------- 
     1 2017-12-04 00:00:00   2 
     2 2017-11-25 00:00:00   3 
+0

Ooh, ordentlich! Ich werde das für das spätere Lesen bookmarken müssen. – kfinity

+0

@kfinity - Ich habe es nicht versucht, aber ich glaube, wenn Sie nach "Oracle match_recognise site: stackoverflow.com" googeln, finden Sie viele Beispiele, wie diese neue Klausel (neu in 12.1) verwendet werden kann, eine sehr vielfältige Palette von Problemen . Ich bewundere ständig seine Kraft und Flexibilität. – mathguy