【问题标题】:Select minimum Seq Num by ID按 ID 选择最小 Seq Num
【发布时间】:2019-06-10 18:17:44
【问题描述】:

只是尝试编写一个简单的查询来获取具有最小CNTCT_SEQ_NUM 的行(每个 VENDOR_ID),其中CONTACT_NAME 不为空。

这是我写的:

SELECT VENDOR_ID, MIN(CNTCT_SEQ_NUM) AS CNTCT_SEQ_NUM , CONTACT_NAME
FROM PS_VENDOR_CNTCT
WHERE VENDOR_ID IN ('ERSUT', 'MOOREA')
AND CONTACT_NAME <> ''
GROUP BY CONTACT_NAME, VENDOR_ID

当前结果:

VENDOR_ID   CNTCT_SEQ_NUM   CONTACT_NAME
ERSUT       19              V Smith
ERSUT       4               T Peterman
ERSUT       2               I GANCE
ERSUT       8               R FISHER
MOOREA      2               S DALY
MOOREA      4               B SLAUTEN
MOOREA      1               N BLAKELY

预期结果是:

VENDOR_ID   CNTCT_SEQ_NUM   CONTACT_NAME
ERSUT       2               I GANCE
MOOREA      1               N BLAKELY

【问题讨论】:

    标签: sql sql-server sql-server-2014


    【解决方案1】:

    试试这个-

    SELECT A.* FROM PS_VENDOR_CNTCT A
    INNER JOIN
    (
        SELECT VENDOR_ID,MIN(CNTCT_SEQ_NUM) CNTCT_SEQ_NUM
        FROM PS_VENDOR_CNTCT
        GROUP BY VENDOR_ID
    )B ON A.VENDOR_ID = B.VENDOR_ID
    AND A.CNTCT_SEQ_NUM = B.CNTCT_SEQ_NUM
    

    【讨论】:

    • 问题 - 为什么这个查询返回 2 行? (两者具有相同的 EFFDT,但一个具有 MIN CNTCT_SEQ_NUM)SELECT VENDOR_ID,MIN(CNTCT_SEQ_NUM) CNTCT_SEQ_NUM, SETID, CONTACT_NAME, EFFDT FROM PS_VENDOR_CNTCT WHERE CONTACT_NAME &lt;&gt; '' AND VENDOR_ID = '05876A' GROUP BY VENDOR_ID, SETID, CONTACT_NAME, EFFDT
    • 1 行用于 ERSUT,1 行用于 MOOREA。它就像 GROUP BY 应用于 VENDOR_ID 一样简单。
    【解决方案2】:

    相关子查询解决了这个问题:

    select vc.*
    from PS_VENDOR_CNTCT vc
    where vc.CNTCT_SEQ_NUM = (select min(vc2.CNTCT_SEQ_NUM)
                              from PS_VENDOR_CNTCT vc2
                              where vc2.VENDOR_ID = vc.VENDOR_ID and
                                    vc2.CONTACT_NAME <> ''
                             );
    

    为了提高性能,您可以尝试使用(VENDOR_ID, CONTACT_NAME, CNTCT_SEQ_NUM) 上的索引。这涵盖了子查询,尽管仍然需要扫描所有索引记录。

    【讨论】:

      【解决方案3】:

      看来你不需要MIN(),而是需要ROW_NUMBER()之类的Window Analytic Function

      SELECT DISTINCT Q.VENDOR_ID, Q.CONTACT_NAME, Q.CNTCT_SEQ_NUM
        FROM
        (
        SELECT P.*, 
               ROW_NUMBER() OVER 
                           (PARTITION BY VENDOR_ID ORDER BY CNTCT_SEQ_NUM) AS RN
          FROM PS_VENDOR_CNTCT P
         WHERE VENDOR_ID IN ('ERSUT', 'MOOREA')
           AND CONTACT_NAME <> ''     
         ) Q
        WHERE Q.RN = 1
      

      【讨论】:

      • 您只需要按VENDOR_ID进行分区。
      猜你喜欢
      • 1970-01-01
      • 2021-07-23
      • 1970-01-01
      • 2013-11-28
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      • 2017-11-06
      • 2016-05-18
      相关资源
      最近更新 更多