2017-02-07 4 views
1

In meinem Projekt habe ich eine Tabelle von e-Mail Benutzer E-Mails:mehr auswählen letzte E-Mails als eine Zeile

|  ID |  PROFILE_ID |  EMAIL | LAST_UPDATED_TIMESTAMP| 
___________________________________________________________________ 
|  1|    1|  [email protected]| 2017-02-02 15:13:46| 
|  2|    1|  [email protected]| 2017-02-01 15:13:46| 
|  3|    2|  [email protected]| 2017-02-03 15:13:46| 

wo PROFILE_ID zu den Benutzerprofilen Tabelle PROFILEN bezieht. Ich möchte 2 (N im Allgemeinen) erhalten jüngste verschiedene E-Mails für jedes Benutzerprofil als eine Zeile:

|  PROFILE_ID |  EMAIL_1 |  EMAIL_2 | 
__________________________________________________ 
|    1|   [email protected]|  [email protected]| 
|    2|   [email protected]|   NULL| 

ich viele Anfragen versucht, das letzte, das ich blieb auf unter:

SELECT 
    EMAIL1.PROFILE_ID, 
    EMAIL1.EMAIL AS EMAIL_1, 
    EMAIL2.EMAIL AS EMAIL_2 
FROM EMAILS EMAIL1 
    LEFT JOIN 
    EMAILS EMAIL2 
    ON EMAIL1.PROFILE_ID = EMAIL2.PROFILE_ID AND EMAIL2.LAST_UPD_TMST <= EMAIL1.LAST_UPD_TMST AND EMAIL1.ID <> EMAIL2.ID 

aber es gibt mir zusätzliche Datensätze für Profil mit mehreren E-Mail:

|  PROFILE_ID |  EMAIL_1 |  EMAIL_2 | 
__________________________________________________ 
|    1|   [email protected]|  [email protected]| 
|    1|   [email protected]|   NULL| 
|    2|   [email protected]|   NULL| 

ich benutze 11g Oracle aber bedenken MySql Kompatibilität wenn möglich halten. Kann jemand sagen, was in der oben erwähnten Frage falsch ist?

+0

Ist 2 die maximale Anzahl von E-Mails pro profile_id? – JohnHC

+0

"Im Allgemeinen wird N" nicht funktionieren, weil in Oracle die Anzahl der Spalten in der Ausgabe zum Zeitpunkt der Analyse bekannt sein muss, lange bevor die Daten überprüft werden - und N ist abhängig von den Daten in der Tabelle. Warum möchten Sie dies in SQL und nicht in Ihrer Berichtsanwendung tun? – mathguy

+0

@JohnHC, nein, pro Profil können mehr als zwei E-Mails vorhanden sein. – Doe

Antwort

0

Eine Methode ist, bedingte Aggregation:

select profile_id, 
     max(case when seqnum = 1 then email end) as email1, 
     max(case when seqnum = 2 then email end) as email2 
from (select e.*, 
      row_number() over (partition by profile_id order by last_updated_timestamp) as seqnum 
     from emails e 
    ) e 
group by profile_id; 

Wenn Sie wirklich um Duplikate entfernen wollen, dann können Sie die Daten vor dem row_number() aggregieren. Um die letzten Auftreten von doppelten E-Mail zu erhalten:

select profile_id, 
     max(case when seqnum = 1 then email end) as email1, 
     max(case when seqnum = 2 then email end) as email2 
from (select e.*, 
      row_number() over (partition by profile_id order by last_updated_timestamp) as seqnum 
     from (select profile_id, email, max(last_updated_timestamp) as last_updated_timestamp 
      from emails e 
      group by profile_id, email 
      ) e 
    ) e 
group by profile_id; 
+0

Vielen Dank für Ihre Antwort. Es sieht so aus, als hätten Sie die rechte Klammer in der Abfrage verpasst: Wählen Sie profile_id, max (case wenn seqnum = 1 dann email end) als email1, max (Fall, wenn seqnum = 2 dann E-Mail-end) als EMAIL2 aus (wählen Sie e. *, row_number() über (Partition von profile_id um durch last_updated_timestamp) ** AS seqnum ** von E-Mails e ) e Gruppe von profile_id; – Doe

2

In 11 Oracle können Sie den PIVOT-Operator verwenden. Ich kenne MySQL nicht, aber ich glaube, es hat keinen PIVOT-Operator.

with 
    test_data (ID, PROFILE_ID, EMAIL, LAST_UPDATED_TIMESTAMP) as (
     select 1, 1, '[email protected]', to_timestamp('2017-02-02 15:13:46', 'yyyy-mm-dd hh24:mi:ss') 
     from dual union all 
     select 2, 1, '[email protected]', to_timestamp('2017-02-01 15:13:46', 'yyyy-mm-dd hh24:mi:ss') 
     from dual union all 
     select 3, 2, '[email protected]', to_timestamp('2017-02-03 15:13:46', 'yyyy-mm-dd hh24:mi:ss') 
     from dual 
    ) 
-- end of test data (not part of the solution); SQL query begins BELOW THIS LINE 
select profile_id, email_1, email_2 
from (select profile_id, email, 
       row_number() over (partition by profile_id 
            order by last_updated_timestamp desc) as rn 
     from test_data 
     ) 
pivot (min(email) for rn in (1 as email_1, 2 as email_2)) 
; 

PROFILE_ID EMAIL_1 EMAIL_2 
---------- ------- ------- 
     1 [email protected] [email protected] 
     2 [email protected] 

2 rows selected. 
+0

danke für die Lösung! Der einzige Kommentar ist, dass diese Abfrage mit der zweiten Abfrage von @GordonLinoff kombiniert werden muss, um Duplikate zu vermeiden und nur eindeutige Werte zu erhalten. – Doe

Verwandte Themen