使用MAX()时避免使用subselect

时间:2012-08-08 17:01:26

标签: sql db2

有没有办法可以避免这种子选择? 我试图使这个查询尽可能高效,并且这样做,试图避免子选择。

我正在寻找ID_NUM表格中最新的替换行。

子选择已到位,因此我只能带回最近更换的行。这是最好的方法吗?

查询完全按照我想要的方式工作,所以请随意忽略最后一个小的子选择。

SELECT   
  A.ID_NUM,
  A.DOB,
  A.NAME,
  A.REPLACED_TMESTMP  
FROM MYTABLE A, MYTABLE B  
WHERE   
  A.ID_NUM = B.ID_NUM
  AND A.REPLACED_TMESTMP IS NOT NULL
  AND B.REPLACED_TMESTMP IS NULL
  AND A.DOB <> B.DOB
  several other conditions...

  AND A.REPLACED_TMESTMP  
    = (SELECT MAX(C.REPLACED_TMESTMP)  
      FROM MYTABLE C  
      WHERE C.ID_NUM = A.ID_NUM  
      AND A.REPLACED_TMESTMP IS NOT NULL  
      )
; 

这里有一些伪代码可以帮助您理解我需要做什么

Select all from table
where a duplicate ID number exists
    that has an active row (no replaced time stamp)
    and has an inactive row(s)
    only bring back the most current replaced row for each ID num.

3 个答案:

答案 0 :(得分:2)

您可以将子选项重新编写为JOIN。我们在这里的一个表上有类似的设置(我们有多个&#34;行&#34;对于每个&#34;事物&#34;,但你只处理&#34;最新&# 34;一个),我通过Visual Explain运行了一个子选择类型查询和一个JOIN类型,根据估计,JOIN将花费相当少的CPU秒来处理(当然,这只是一个估计,而你的桌子可能与我的大不相同,所以请带上一粒盐。)

我稍微更改了查询,我认为这应该包含您正在寻找的所有信息。

SELECT INACTIVE.ID_NUM
      ,INACTIVE.DOB
      ,INACTIVE.NAME,
      ,INACTIVE.REPLACED_TMESTMP  
FROM (
    SELECT *
    FROM MYTABLE
    WHERE REPLACED_TMESTMP IS NULL
) AS ACTIVE
JOIN (
    SELECT *
    FROM MYTABLE
    WHERE REPLACED_TMESTMP IS NOT NULL
) AS INACTIVE
  ON ACTIVE.ID_NUM = INACTIVE.ID_NUM
 AND ACTIVE.DOB   <> INACTIVE.DOB
  -- several other conditions...

JOIN (
    SELECT ID_NUM,
           MAX(REPLACED_TMESTMP) AS TIMESTAMP
    FROM MYTABLE
    GROUP BY ID_NUM
) MAX_REPLACE
  ON INACTIVE.ID_NUM           = MAX_REPLACE.ID_NUM
 AND INACTIVE.REPLACED_TMESTMP = MAX_REPLACE.TIMESTAMP

答案 1 :(得分:1)

SELECT   
  A.ID_NUM,  
  MAX(A.REPLACED_TMESTMP) AS MOST_RECENT_REPLACED_ROW
FROM MYTABLE A,
     MYTABLE B
WHERE   
    A.ID_NUM = B.ID_NUM
    AND A.REPLACED_TMESTMP IS NOT NULL
    AND B.REPLACED_TMESTMP IS NULL
GROUP BY A.ID_NUM
;

答案 2 :(得分:1)

如果您的DB2版本支持ROW_NUMBER()函数,您可以执行以下操作:

WITH ranked AS (
  SELECT
    ROW_NUMBER() OVER (
      PARTITION BY replaced.ID_NUM
      ORDER BY replaced.REPLACED_TMESTMP DESC
    ) AS rnk.
    replaced.ID_NUM,
    replaced.REPLACED_TMESTMP,
    replaced.... /* other columns as necessary */
  FROM MYTABLE replaced
    INNER JOIN MYTABLE active ON replaced.ID_NUM = active.ID_NUM
  WHERE replaced.REPLACED_TMESTMP IS NOT NULL
    AND active.REPLACED_TMESTMP IS NULL
    AND ... /* your other conditions */
)
SELECT
  ID_NUM,
  REPLACED_TMESTMP,
  ...
FROM ranked
WHERE rnk = 1
;

ROW_NUMBER()函数将数字分配给REPLACED_TMESTMP不为空的行,按该列的降序排列,按ID_NUM分区。然后,主SELECT只检索排名为1的行。