2013-06-04 57 views
2

我有一個類似於以下的場景,我想要做的就是找到最多三列 - 這似乎是一個非常冗長的方法,我用它來找到列mx最大的幾列

什麼是更簡潔更優雅的解決方案?

CREATE TABLE #Pig 
(
    PigName CHAR(1), 
    PigEarlyAge INT, 
    PigMiddleAge INT, 
    PigOldAge INT 
) 

INSERT INTO #Pig VALUES 
('x',5,2,3), 
('y',2,9,5), 
('z',1,1,8); 

WITH Mx_cte 
    AS 
    (
    SELECT PigName, 
      Age = PigEarlyAge 
    FROM #Pig 
    UNION 
    SELECT PigName, 
      Age = PigMiddleAge 
    FROM #Pig 
    UNION 
    SELECT PigName, 
      Age = PigOldAge 
    FROM #Pig 
    ) 
SELECT x.PigName, 
     x.PigEarlyAge, 
     x.PigMiddleAge, 
     x.PigOldAge, 
     y.mx 
FROM #Pig x 
     INNER JOIN 
     (
     SELECT PigName, 
       mx = Max(Age) 
     FROM Mx_cte 
     GROUP BY PigName 
     ) y 
     ON 
      x.PigName = y.PigName 
+0

你的意思是你只需要最大的年齡總結? –

+0

@YuriyGalanter - 不,結果應該與我在帖子中包含的腳本完全一樣 - 如果這有點含糊不清,請道歉。 – whytheq

回答

4

SQL Server在接受值列表並返回最大值的其他RDBMS中沒有等效的GREATEST函數。

但是,您可以通過使用由所需列組成的table valued constructor然後將MAX應用於此來模擬類似的事情。

SELECT *, 
     (SELECT MAX(Age) 
     FROM (VALUES(PigEarlyAge), 
         (PigMiddleAge), 
         (PigOldAge)) V(Age)) AS mx 
FROM #Pig 
+0

+1簡潔 - 像所謂的'VALUES'的用法是什麼? - 我在MSDN上搜索什麼詞組? – whytheq

+1

@whytheq [表值構造函數](http://msdn.microsoft.com/en-us/library/dd776382.aspx) –

+0

感謝您的鏈接 - 看起來像你有一種相關的TVC? – whytheq

0

如果你需要不同年齡的組合MAX,你可以簡單的將它們添加的最大功能的內部:

SELECT PigName, MAX(PigEarlyAge + PigMiddleAge + PigOldAge) as MaxAge 
FROM #Pig 
GROUP BY PigName 
+0

也許我的問題有點模糊 - 我想要的結果與OP爲MaxAge返回一樣....我只是希望能夠以更短的方式查詢它。 – whytheq

1

如果你想在三個字段的最大:

select (case when max(PigEarlyAge) >= max(PigMiddleAge) and max(PigEarlyAge) >= max(PigOldAge) 
       then max(PigEarlyAge) 
       when max(PigMiddleAge) >= max(PigOldAge) 
       then max(PigMiddleAge) 
       else max(PigOldAge) 
     end) 
    from #Pig 

如果您正在查找具有相應最大值的行,請使用row_number()以及union

select p.PigName, PigEarlyAge, PigMiddleAge, PigOldAge, 
     (case when PigEarlyAge >= PigMiddleAge and PigEarlyAge >= PigOldAge then PigEarlyAge 
      when PigMiddleAge >= PigOldAge then PigMiddleAge 
      else PigOldAge 
     end) as BigAge 
from (select p.*, 
      row_number() over 
        (order by (case when PigEarlyAge >= PigMiddleAge and PigEarlyAge >= PigOldAge then PigEarlyAge 
            when PigMiddleAge >= PigOldAge then PigMiddleAge 
            else PigOldAge 
           end) desc 
        ) seqnum as seqnum 
     from #Pig p 
    ) p 
where p.seqnum = 1; 

如果您想要重複值,則使用rank()而不是row_number()

+0

感謝戈登 - +1有趣的職位。 – whytheq