【问题标题】:How to write sql SELECT query to for this problem?如何为这个问题编写 sql SELECT 查询?
【发布时间】:2019-11-26 05:29:54
【问题描述】:

考虑下面的 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

我尝试了各种查询,但似乎都无法获得我期望的结果,因为它会导致由于 group by 的错误。

【问题讨论】:

    标签: sql oracle oracle-sqldeveloper plsqldeveloper


    【解决方案1】:

    这似乎是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;
    

    【讨论】:

    • 我认为第一个查询不会作为es.status 列也需要在GROUP BY 子句中运行
    【解决方案2】:

    这是一种稍微不同的方法,使用 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
    

    我相信这就是您正在寻找的。​​p>

    【讨论】:

      【解决方案3】:
        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;
      

      【讨论】:

      • 在 GROUP BY 子句中需要es.status 列并且还需要做LEFT JOIN
      猜你喜欢
      • 1970-01-01
      • 2018-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-30
      • 1970-01-01
      相关资源
      最近更新 更多