如何编写sql SELECT查询以解决此问题?

时间:2019-07-17 11:32:55

标签: sql oracle oracle-sqldeveloper plsqldeveloper

考虑下面的2个表格

详细信息表:-

email    Name    Region   PostalCode
a@b.com  Mike    US-east    1234
a@b.com  Sara    US-east    2341
a@b.com  Sara    US-west    1234
b@c.com  Ash     US-west    6542
b@c.com  Cindy   US-west    4213
c@d.com  George  US-east    1234
c@d.com  Thomas  US-east    3412

EMAIL_STATUS表:-

email    status  
a@b.com  In progress     
c@d.com  Resolved

我需要左连接表(左是DETAILS表,右是EMAIL_STATUS表)的查询,并且每封电子邮件仅获取一行

预期结果:-

email    Name    Region   PostalCode  status        count(*)
a@b.com  Mike    US-east    1234  In progress       3
b@c.com  Ash     US-west    6542  null              2
c@d.com  George  US-east    1234  Resolved          2

我尝试了各种查询,但是似乎没有一种方法能获得我期望的结果,因为它会因分组依据而导致错误。

3 个答案:

答案 0 :(得分:3)

这似乎是left joingroup by

select d.email, min(d.name) as name, min(d.region) as region,
       min(d.postalcode) as postalcode,
       es.status, count(*) as cnt
from details d left join
     email_status es
     on d.email = es.email
group by d.email, es.status;

以上内容为每封电子邮件返回一行。如果要特定行,请使用row_number()count(*)

select d.*,
       es.status, d.cnt
from (select d.*,
             count(*) over (partition by email) as cnt,
             row_number() over (partition by email order by ?) as seqnum  -- the ? describes which row you want
      from details d
     ) d left join
     email_status es
     on d.email = es.email;

答案 1 :(得分:1)

这是一种略有不同的方法,使用LAG确定您是否正在查看特定电子邮件地址的第一行:

WITH DETAIL_COUNT AS (SELECT EMAIL, COUNT(*) AS EMAIL_COUNT
                        FROM DETAILS
                        GROUP BY EMAIL),
     ALL_ROWS AS (SELECT d.EMAIL,
                         d.NAME,
                         d.REGION,
                         d.POSTAL_CODE,
                         e.STATUS,
                         dc.EMAIL_COUNT,
                         LAG(d.EMAIL, 1) OVER (ORDER BY d.EMAIL, d.NAME) AS PREV_EMAIL
                    FROM DETAILS d
                    LEFT OUTER JOIN EMAIL_STATUS e
                      ON e.EMAIL = d.EMAIL
                    LEFT OUTER JOIN DETAIL_COUNT dc
                      ON dc.EMAIL = d.EMAIL
                    ORDER BY d.EMAIL, d.NAME)
SELECT EMAIL, NAME, REGION, POSTAL_CODE, STATUS, EMAIL_COUNT
  FROM ALL_ROWS
  WHERE PREV_EMAIL IS NULL OR
        PREV_EMAIL <> EMAIL

这将产生结果:

EMAIL   NAME    REGION  POSTAL_CODE STATUS      EMAIL_COUNT
a@b.com Mike    US-east 1234        In progress 3
b@c.com Ash     US-west 6542                    2
c@d.com George  US-east 1234        Resolved    2

我相信这是您要寻找的。

答案 2 :(得分:0)

  Select d.email, min(d.name) As name, min(d.region) as region,
         min(d.postalcode) as postalcode,
         es.status, count(*) As cnt
    From details d  
    Join email_status es
      On d.email = es.email
Group By d.email;