2017-02-07 68 views
1

在我的項目我有用戶的電子郵件郵件表:選擇最近的幾封電子郵件作爲一個行

|  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| 

其中PROFILE_ID指用戶配置表中的配置文件。我想獲得2(通常N)最近爲每個用戶輪廓不同的郵件作爲一個行:

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

我試了很多疑問,最後一個我停在低於:

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 

,但它讓我對配置文件包含幾封電子郵件額外的記錄:

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

我用的Oracle 11g,但如果可能的話牢記MySQL的兼容性。任何人都可以說在上面提到的查詢中有什麼錯誤?

+0

是2每個profile_id的最大郵件數量? – JohnHC

+0

「通常情況下,N」不起作用,因爲在Oracle中,輸出中的列數必須在分析時已知,在數據被檢查之前很久 - 而N取決於表中的數據。爲什麼你想在SQL中而不是在你的報告應用程序中做到這一點? – mathguy

+0

@JohnHC,不,每個配置文件可能會有兩個以上的電子郵件。 – Doe

回答

0

一種方法是有條件聚集:

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; 

如果你確實要刪除重複項,那麼你就可以在row_number()前彙總數據。要獲得重複的電子郵件的最後發生:

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

感謝您的回覆,看起來您在查詢中錯過了右括號:select profile_id, max(seqnum = 1,則電子郵件結束時)爲email1, MAX(情況下,當SEQNUM = 2,則電子郵件端)作爲EMAIL2 從(選擇e。*, ROW_NUMBER()以上(從電子郵件Ë 分區由PROFILE_ID爲了通過LAST_UPDATED_TIMESTAMP)** AS SEQNUM ** )在線 組通過profile_id; – Doe

2

在Oracle 11你可以使用PIVOT運算符。我不知道MySQL,但我相信它沒有PIVOT運營商。

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

感謝您的解決方案!唯一的評論是,這個查詢必須與@GordonLinoff的第二個查詢結合起來,以避免重複並獲得唯一值。 – Doe

相關問題