2016-08-24 2 views
0

Ich arbeite derzeit mit drei verschiedenen Tabellen, dieJoining drei verschiedenen Tabellen mit Datumsspalten und Gruppe von Datum

Benutzer wie folgt aussehen:

user_id|createtime 
----------------------------- 
001  2016-07-20 
002  2016-08-15 
003  2016-08-05 
004  2016-08-23 

Objekt:

objc_id|createtime|user_id 
----------------------------- 
001  2016-07-20 001 
002  2016-07-15 001 
003  2016-08-05 002 
004  2016-08-23 001 
005  2016-08-19 003 
006  2016-08-21 004 
007  2016-08-22 004 

Veranstaltung :

event_id|createtime|objc_id 
----------------------------- 
001  2016-08-25 001 
002  2016-08-26 004 
003  2016-08-28 002 
004  2016-08-27 005 
005  2016-08-30 003 

Ich habe bereits select-Anweisungen, die mir sagen, wie viele neue Benutzer, Objekte oder Ereignisse an einem bestimmten Datum erstellt wurden:

select createtime, count(user_id) as new_user from 
user where createtime >= CURRENT_DATE - INTERVAL '30 days' group by 
createtime; 

select createtime, count(objc_id) as new_objc from 
object createtime >= CURRENT_DATE - INTERVAL '30 days' group by createtime; 

select createtime, count (event_id) from 
event where createtime >= CURRENT_DATE - INTERVAL '30 days' 
group by createtime; 

Jetzt möchte ich eine Select-Anweisung machen, wo alle Zahlen neuer Objekte, Benutzer und Ereignisse werden angezeigt und nach ihrer Erstellungszeit gruppiert.

Allerdings kann ich dafür keine Lösung finden. Das Ziel zu erreichen, würde wie folgt aussehen:

createtime|new_user|new_objc|new_event 
--------------------------------------- 
2016-07-15    1 
2016-07-20 1   1 
2016-07-22  
2016-07-24 
2016-08-05 1   1 
2016-08-15 1 
2016-08-19    1 
2016-08-21    1 
2016-08-22    1 
2016-08-23 1   1 
2016-08-25      1 
2016-08-26      1 
2016-08-27      1 
2016-08-28      1 
2016-08-30      1 

... natürlich auch einige Daten mehr als einmal für eine Gruppe erscheinen könnten, so dass die Zahl 1 oder höher sein wird.

Ziel ist es zu sehen, ob das Marketing die Anzahl der neuen Nutzer erhöht, Objekte kauft und im Laufe der Zeit an einem Event teilnimmt (Sie benötigen das Objekt für das Event).

Hat jemand eine Lösung dafür, oder muss ich mit separaten Ergebnistabellen gehen?

Antwort

0
SELECT 
    Createtime 
    ,COUNT(DISTINCT user_id) as new_user 
    ,COUNT(DISTINCT objc_id) as new_objc 
    ,COUNT(DISTINCT new_event) as new_objc 
FROM (
    SELECT Createtime, user_id, CAST(NULL AS INT) as objc_id, CAST(NULL as INT) as event_id 
    FROM 
     users 
    WHERE createtime >= CURRENT_DATE - INTERVAL '30 days' 
    UNION ALL 
    SELECT Createtime, CAST(NULL AS INT) as user_id, objc_id, CAST(NULL as INT) event_id 
    FROM 
     object 
    WHERE createtime >= CURRENT_DATE - INTERVAL '30 days' 
    UNION ALL 
    SELECT Createtime, CAST(NULL AS INT) as user_id, CAST(NULL AS INT) as objc_id, event_id 
    FROM 
     event 
    WHERE createtime >= CURRENT_DATE - INTERVAL '30 days' 
) t 
GROUP BY 
    Createtime 
ORDER BY 
    Createtime 

Beim ersten Blick auf Ihre Frage sieht es aus wie Sie eine Verknüpfung benötigen, aber die Realität ist, was Sie brauchen um alle zu vereinen und zu zählen(). Ich zähle DISTINCT, was redundant sein sollte, da user_id, objc_id, event_id eindeutige Primärschlüssel zu sein scheinen.

-1

Verwenden Sie Ihre drei SELECT-Anweisungen als Unterabfragen in einem erweiterten Join.

SELECT A.createtime, A.new_user, B.new_objc, C.new_event 
FROM (
    select createtime, count(user_id) as new_user from 
    user where createtime >= CURRENT_DATE - INTERVAL '30 days' group by 
    createtime; 
) A INNER JOIN (
    select createtime, count(objc_id) as new_objc from 
    object createtime >= CURRENT_DATE - INTERVAL '30 days' group by createtime; 
) B ON A.createtime = B.createtime INNER JOIN (
    select createtime, count (event_id) as new_event from 
    event where createtime >= CURRENT_DATE - INTERVAL '30 days' 
    group by createtime; 
) C ON B.createtime = C.createtime 
+0

Was ist, wenn es eine Erstellungszeit gibt, die von Benutzern in Objekt oder Ereignis fehlt? Dies wird diese Ergebnisse entfernen. – Matt

0

wenn Sie wollen nicht Ihre Abfragen verwenden versuchen Sie dies:

SELECT T1.createtime , COUNT(U.user_id) new_user , 
     COUNT(O.objc_id) new_objc , COUNT(E.event_id) new_event 
FROM (((SELECT distinct createtime from user 
     WHERE createtime >= CURRENT_DATE - INTERVAL '30 days' 
     UNION 
     SELECT distinct createtime from object 
     WHERE createtime >= CURRENT_DATE - INTERVAL '30 days' 
     UNION 
     SELECT distinct createtime from event 
     WHERE createtime >= CURRENT_DATE - INTERVAL '30 days' 
     ) as T1 
     LEFT JOIN user U ON T1.createtime = U.createtime) 
     LEFT JOIN object O ON O.createtime = T1.createtime) 
     LEFT JOIN join event E ON E.createtime = T1.createtime) 
GROUP BY T1.createtime ORDER BY T1.createtime; 
+0

Also, weil Sie t1 aus den Tabellen ableiten, bedeutet der vollständige äußere Join, dass nie ein rechtes äußeres Ergebnis zurückgegeben wird, aber LINKER JOIN wäre passender. Auch die Begrenzung der Erstellungszeit in einem großen Dataset sollte besser sein, wenn Sie es in Ihren union-Anweisungen tun. – Matt

+0

@Matt das ist richtig, über die Begrenzung der Createtime in der großen Datenmenge, Bearbeitung jetzt. – alibttb

+0

Die Version funktioniert auch gut, aber ich habe die T2.createtime in T1 und eine Bestellung von T1.createtime für eine bessere Übersicht geändert. Vielen Dank für Ihre Hilfe! – user3906778