2016-08-16 55 views
1

我已經生成了一個廣泛的視圖,它根據不同的統計模型模擬某些事件。這些模型在每個列標題中由數字定義,並且行的最大值是最佳模型。獲取保存行的最大值的列名稱

生成的表格看起來(部分)如下;

+--------+----+------+------+------+------+------+------+ 
| Number | LI | PHSE | 0505 | 0506 | 0507 | 0508 | 0509 | [...] etc. 
+--------+----+------+------+------+------+------+------+ 
| 100254 | 2 | M1 | 44 | 46 | 45 | 44 | 44 | 
| 100254 | 2 | M2 | 36 | 36 | 35 | 37 | 37 | 
| 100254 | 2 | M3 | 5 | 5 | 5 | 5 | 5 | 
| 100254 | 2 | R1 | 34 | 36 | 37 | 37 | 37 | 
| 100254 | 2 | R2 | 41 | 41 | 40 | 41 | 41 | 
| 100329 | 1 | M1 | 37 | 38 | 38 | 38 | 39 | 
| 100329 | 1 | M2 | 31 | 29 | 28 | 29 | 29 | 
| 100329 | 1 | M3 | 6 | 6 | 6 | 6 | 6 | 
| 100329 | 1 | R1 | 29 | 29 | 29 | 30 | 30 | 
| 100329 | 1 | R2 | 25 | 26 | 26 | 27 | 26 | 
+--------+----+------+------+------+------+------+------+ 
    [...] etc. 

現在我想找到每個行中的最高值,並顯示相應的列名作爲這樣的;

| Number | LI | PHSE | MAXCOL | 
+--------+----+------+--------+ 
| 100254 | 2 | M1 | 0506 | 
| 100254 | 2 | M2 | 0508 | 
| 100254 | 2 | M3 | 0505 | 
| 100254 | 2 | R1 | 0507 | 
| 100254 | 2 | R2 | 0505 | 
+--------+----+------+--------+ 
    [...] etc. 

這是從100254衍生 - 2 - M1最大值46 0506列發生等

我一直在PIVOT功能,但沒有成功,有玩弄周圍。我也尋找一個類似於Excel的索引/匹配等價物,但由於我無法將列標題作爲值來引用,所以這顯然不起作用(並且還沒有找到這樣的函數)。

任何幫助將非常感激。每達明的評論


UPDATE:

從代碼的摘錄,導致此:

SELECT DISTINCT sub2.Number, sub2.LI, sub2.PHSE 
, sum(sub2.[0505]) over (partition by sub2.Number, sub2.LI, sub2.PHSE) as '0505' 
, sum(sub2.[0506]) over (partition by sub2.Number, sub2.LI, sub2.PHSE) as '0506' 
[...] etc. /*64 rows*/ 

FROM 
    (SELECT DISTINCT sub.* 
    , CASE WHEN sub.MF > sub.[5PAV] - sub.[5PSTDEV] THEN 1 ELSE 0 END AS '0505' 
    , CASE WHEN sub.MF > sub.[5PAV] - sub.[6PSTDEV] THEN 1 ELSE 0 END AS '0506' 
    [...] etc. /*64 rows*/ 

    FROM 
     (SELECT DISTINCT ra.* 
     , sum(ra.qtyr) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND 1 preceding)/
     sum(ra.qtyu) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND 1 preceding) AS '5PAV' 
     , sum(ra.qtyr) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 6 preceding AND 1 preceding)/
     sum(ra.qtyu) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 6 preceding AND 1 preceding) AS '6PAV' 
     [...] etc. /*8 rows*/ 

     , stdev(ra.MF) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 4 preceding AND CURRENT row) AS '5PSTDEV' 
     , stdev(ra.MF) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND CURRENT row) AS '6PSTDEV' 
     [...] etc. /*8 rows*/ 

     FROM ra 
     ) AS sub 
    ) AS sub2 

毫無疑問,這可能是SQL最無效的用途之一,但時間壓力和經驗不足使我這樣寫。

任何建議來更改此代碼,並更有效地實現所需的表結果,也將不勝感激。


編輯每安東的答案;

總結爲pvt的上述代碼繼續如下;

SELECT Number, LI, PHSE, combo, hitrate 

FROM (...) AS pvt 
UNPIVOT 
(Hitrate FOR Combo IN (
         [0505], 
         [0506], 
         [...] etc.)) AS upvt 

偉大的解決方案,一個不雅的問題。

+0

你做了處理數據庫表,如果它是一個電子表格的錯誤。它不是,而且你最終還是a)重複包含相同「類型」數據的列,b)數據不作爲數據存儲,而是存儲在元數據(這裏是列名)中。如果您首先正確地建模了數據(模型和值有兩列,還有更多行但列較少),查詢將很容易編寫。 –

+0

@Damien_The_Unbeliever這是有道理的。數據是通過這種格式的子查詢生成的,所以源代碼不是問題。這是我應用於這一點的方法,似乎無效;儘管'unpivot'按照您的建議重新排列了數據,但這似乎是一種非常無效的繞行方式。我將編輯上面的問題來縮小這個範圍,看看代碼如何變得更高效。考慮到所有涉及的變量,我已經儘可能在Excel中使用聚合函數來編寫查詢。我知道這很愚蠢,但時間壓力和有限的經驗讓我想到這個方法 – Sambo

回答

0

我會用CROSS APPLY作爲如下:

WITH Src AS 
(
    SELECT * FROM (VALUES 
    (100254, 2, 'M1', 44, 46, 45, 44, 44), 
    (100254, 2, 'M2', 36, 36, 35, 37, 37), 
    (100254, 2, 'M3', 5, 5, 5, 5, 5), 
    (100254, 2, 'R1', 34, 36, 37, 37, 37), 
    (100254, 2, 'R2', 41, 41, 40, 41, 41), 
    (100329, 1, 'M1', 37, 38, 38, 38, 39), 
    (100329, 1, 'M2', 31, 29, 28, 29, 29), 
    (100329, 1, 'M3', 6, 6, 6, 6, 6), 
    (100329, 1, 'R1', 29, 29, 29, 30, 30), 
    (100329, 1, 'R2', 25, 26, 26, 27, 26)) T(Number, LI, PHSE, [0505], [0506], [0507], [0508], [0509]) 
) 
SELECT Number, LI, PHSE, MaxCol 
FROM Src 
CROSS APPLY (SELECT TOP 1 * FROM (VALUES 
    ('0505', [0505]), 
    ('0506', [0506]), 
    ('0507', [0507]), 
    ('0508', [0508]), 
    ('0509', [0509]) 
    ) T(MaxCol, Val) ORDER BY Val DESC) Q 

請注意,除非指定了一些附加值,否則可以隨機選擇相等的列,即MaxCol。

更新 你需要動態查詢,如下列之一:

DECLARE @sql nvarchar(MAX) = 
    'SELECT Number, LI, PHSE, MaxCol 
FROM Src 
CROSS APPLY (SELECT TOP 1 * FROM (VALUES' +STUFF(
    (SELECT ',(', QUOTENAME(name, '''')+','+QUOTENAME(name)+')' 
    FROM sys.columns 
    WHERE object_id=OBJECT_ID('Src') AND name NOT IN ('Number', 'LI', 'PHSE') 
    FOR XML PATH('')), 1, 1, '')+') T(MaxCol, Val) ORDER BY Val DESC) Q'; 
EXEC(@sql); 

Src是你的表名,因此替換它。

+0

謝謝,但表格中有64列和52K條記錄。沒有選項... – Sambo

+0

在這種情況下,您需要動態查詢,查看更新後的答案。 –

0

如果你想看到所有MAXCOL(等於列)試試這個:

CREATE TABLE table1 (
Number NUMERIC(10), 
LI numeric(10), 
PHSE NVARCHAR(10), 
[0505] numeric(10), 
[0506] numeric(10), 
[0507] numeric(10), 
[0508] numeric(10), 
[0509] numeric(10)) 

INSERT INTO table1 VALUES(100254,2,'M1',44 ,46 ,45 ,44,44) 
INSERT INTO table1 VALUES(100254,2,'M2',36,36,35,37,37) 
INSERT INTO table1 VALUES(100254,2,'M3',5,5,5,5,5) 
INSERT INTO table1 VALUES(100254,2,'R1',34,36,37,37,37) 
INSERT INTO table1 VALUES(100254,2, 'R2',41,41,40,41,41) 
INSERT INTO table1 VALUES(100329,1, 'M1',37,38,38,38,39) 
INSERT INTO table1 VALUES(100329,1, 'M2',31,29,28,29,29) 
INSERT INTO table1 VALUES(100329,1, 'M3',6,6,6,6,6) 
INSERT INTO table1 VALUES(100329,1, 'R1',29,29,29,30,30) 
INSERT INTO table1 VALUES(100329,1, 'R2',25,26,26,27,26) 

SELECT * 
INTO #UNPIVOT 
FROM table1 
UNPIVOT (num 
FOR MAXCOL IN ([0505],[0506],[0507],[0508],[0509])) AS k 

SELECT A.Number,A.LI,A.PHSE,A.num,B.MAXCOL FROM 
(SELECT number,LI,PHSE,MAX(num) AS num FROM #UNPIVOT GROUP BY number,LI,PHSE) A 
LEFT JOIN 
(SELECT * FROM #UNPIVOT) B ON A.num=B.num AND A.Number=B.Number AND A.LI=B.LI AND A.PHSE=B.PHSE 
+0

謝謝,但是表中有64列和52K記錄下來。不是一個選項... – Sambo