2016-08-16 61 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

相关问题