2010-10-01 77 views
6

選擇列名我有一個查詢是這樣的:從最大查詢

;WITH t as 
(
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1], 20 as [Col2], 20 as [Col3], 20 as [Col4] UNION ALL 
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1], 30 as [Col2], 40 as [Col3], 50 as [Col4] 
) 
SELECT RowNumber, ObjectID, 
     (
     SELECT MAX(Amount) 
     FROM (
       SELECT [Col1] AS Amount 
       UNION ALL 
       SELECT [Col2] 
       UNION ALL 
       SELECT [Col3] 
       UNION ALL 
       SELECT [Col4] 
       ) d 
     WHERE Amount > 0 
     ) 
FROM t 

查詢工作正常,但我想知道的是馬克斯(金額)的由來。 (RowNumber,ObjectId,Amount)我想要列(Col1,Col2,Col3,Col4)的名稱作爲字符串。

有沒有辦法做到這一點?

編輯 問題來自評論:如果兩列有相同的最大值,它可能是一個?是的,它可以是任何一個。只要我知道它可能來自哪裏,任何列名都會執行。

使用SQL Server 2008

+0

您正在使用什麼RDBMS? – 2010-10-01 20:03:33

+1

如果Col1和Col2具有相同的MAX,該怎麼辦?它可能是一個......? – gbn 2010-10-01 20:05:40

+0

希望你不介意我剛剛編輯你的代碼,使它成爲一個可運行的例子,因爲我從來沒有見過這種方法。隨意將它滾回去! – 2010-10-01 20:20:58

回答

1

一個步驟中,您可以使用UNPIVOTOUTER APPLY組合:

;WITH t as  (
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1], 20 as [Col2], 
     20 as [Col3], 20 as [Col4] UNION ALL 
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1], 30 as [Col2], 
     40 as [Col3], 50 as [Col4]) 
SELECT 
    RowNumber, 
    ObjectID, 
    ColName, 
    ColAmount 
FROM t 
OUTER APPLY (
    SELECT TOP 1 
    ColName, 
    ColAmount 
    FROM 
    (
     SELECT 
     Col1, 
     Col2, 
     Col3, 
     Col4 
    ) x 
    UNPIVOT (
     ColAmount FOR ColName IN (Col1, Col2, Col3, Col4) 
    ) y 
    WHERE ColAmount > 0 
    ORDER BY ColAmount DESC 
) z 

結果:

RowNumber ObjectID ColName ColAmount 
----------- ----------- --------- ----------- 
1   1   Col2  20 
2   2   Col4  50 
+0

謝謝,這原來是最好的解決方案。不知道UNPIVOT的功能,但這正是我所需要的。 – 2010-10-04 15:31:24

5

不要MAX:使用TOP避免聚合/ GROUP BY。

它還可以處理使用WITH TIES重複

我不知道,如果你遇到了什麼是僞代碼或者一個子查詢,但這應該做你想做的

SELECT TOP 1 -- WITH TIES if needed 
    * 
FROM 
    (
    SELECT RowNumber, ObjectID, [Col1] AS Amount, 'Col1' AS ColName 
    FROM table 
    UNION ALL 
    SELECT RowNumber, ObjectID, [Col2], 'Col2' AS ColName 
    FROM table 
    UNION ALL 
    SELECT RowNumber, ObjectID, [Col3], 'Col3' AS ColName 
    FROM table 
    UNION ALL 
    SELECT RowNumber, ObjectID, [Col4], 'Col4' AS ColName 
    FROM table 
    ) foo 
WHERE Amount > 0 
ORDER BY Amount DESC 

你的主要問題是,無論你如何操作,你都必須觸碰表格4次,因爲子查詢只返回一個值。我看不到ROW_NUMBER解決方案(但是可能有一個雖然... :-)

+0

他的查詢是每行進行的。我從來不知道你能做到這一點。 – 2010-10-01 20:16:16

+0

@Martin Smith:它有效,但我不確定如何獲取列名,因爲它是隻允許一個值的子查詢。請參閱以下鏈接:http://sqlblogcasts.com/blogs/simons/archive/2006/05/08/Neat-trick-to-find-max-value-of-multiple-columns.aspx或http:// sqlblogcasts。 com/blogs/simons/archive/2006/05/16/Performance-of-MAX-trick.aspx – gbn 2010-10-01 20:20:03

+0

是以前從未見過的。感謝您的鏈接! – 2010-10-01 20:22:59

3

這是未經測試的:但是要查看您的數據正在發生什麼,這可能有所幫助。不是真正的產品代碼質量:

SELECT RowNumber, ObjectID, 
     (
     SELECT MAX(Amount) 
     FROM (
       SELECT str([Col1]) + ", col1, " AS Amount 
       UNION ALL 
       SELECT str([Col2]) + ", col2" 
       UNION ALL 
       SELECT str([Col3]) + ", col3" 
       UNION ALL 
       SELECT str([Col4]) + ", col4" 
       ) 
     WHERE Amount > 0 
     ) 
FROM table 

str()是DBMS的「toString()」函數。 你的SQL看起來很奇怪,你使用的是什麼DBMS?

+0

你必須有金額>'0',但這是相當整潔+ 1 – gbn 2010-10-01 20:25:59

+0

這是一個聰明的方式來做到這一點。沒有考慮將列名添加爲像這樣的字符串。謝謝 – 2010-10-01 20:34:52

2

添加到user202553's answer

;WITH t1 as(
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1], 20 as [Col2], 20 as [Col3], 20 as [Col4] UNION ALL 
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1], 30 as [Col2], 40 as [Col3], 50000045 as [Col4] 
), 
t2 as(
SELECT RowNumber, ObjectID, 
     (
     SELECT TOP 1 CAST(C AS BINARY(4)) + CAST(Amount as BINARY(4)) 
     FROM (
       SELECT 'Col1' AS C, [Col1] AS Amount 
       UNION ALL 
       SELECT 'Col2' AS C, [Col2] 
       UNION ALL 
       SELECT 'Col3' AS C, [Col3] 
       UNION ALL 
       SELECT 'Col4' AS C, [Col4] 
       ) d 
     WHERE Amount > 0 
     ORDER BY Amount desc 
     ) AS Top1 
FROM t1 
) 
SELECT RowNumber, 
     ObjectID, 
     CAST(Left(Top1, 4) AS CHAR(4)) AS Col, 
     CAST(SUBSTRING(Top1,5,4) AS INT) AS Amount 
FROM t2 
+0

謝謝,這也相當乾淨 – 2010-10-02 00:48:44

+0

甚至整潔的字符串concat:固定長度的「編碼」 – gbn 2010-10-03 09:21:17