2017-02-07 37 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

相关问题