2011-02-27 114 views
0

可以说,我有这样一个表:垂直选择的结果,而不是水平的结果SQL服务器

a  b c  d e  f 
--------------------------------- 
1.2 2.3 4.4 5.1 6.7 11.9 
7.2 2.3 4.3 5.1 4.7 3.9 
1.9 5.3 3.3 5.1 3.7 8.9 
5.2 2.7 7.4 9.1 1.7 2.9 

如果非要计算一些东西作为列的和的乘积的平方根

SQRT(sum(a*a)), SQRT(sum(a*b)), SQRT(sum(a*c)), SQRT(sum(a*d)), SQRT(sum(a*e)), 
SQRT(sum(a*f)), SQRT(sum(b*b)), SQRT(sum(b*c)), SQRT(sum(b*d)).... SQRT(sum(f*f)) 

结果:

id result operation 
----------------------------- 
1 x  a*a 
2 y  a*b 
... ...  ... 
n z  f*f 

代替:

a*a  a*b ...  f*f 
---------------------------- 
x  y ...  z 

目前查询是

SELECT SQRT(sum(a*a)) AS a*a, SQRT(sum(a*b)) AS a*b, ... , SQRT(sum(f*f)) AS f*f 
FROM Sometable 
+0

这似乎是http://stackoverflow.com/questions/5111412/multi-threading-in-sql-server – Thomas

回答

1
DECLARE @T TABLE(
id INT PRIMARY KEY, 
a FLOAT, 
b FLOAT, 
c FLOAT, 
d FLOAT, 
e FLOAT, 
f FLOAT 
) 

INSERT INTO @T 
SELECT * FROM (VALUES 
(1, 1.2,2.3,4.4,5.1,6.7,11.9), 
(2, 7.2,2.3,4.3,5.1,4.7,3.9), 
(3, 1.9,5.3,3.3,5.1,3.7,8.9), 
(4, 5.2,2.7,7.4,9.1,1.7,2.9)) T(id,a,b,c,d,e, f) 

;WITH U AS 
(
SELECT * 
FROM @T 
UNPIVOT (o FOR col IN (a,b,c,d,e, f)) unpvt 
) 
SELECT u1.col + '*' + u2.col as operation, SQRT(sum(u1.o*u2.o)) AS result 
FROM U u1 JOIN U u2 ON u1.id=u2.id AND u1.col <= u2.col 
GROUP BY u2.col, u1.col 
ORDER BY u2.col, u1.col 
+0

可否请您解释一下这些行:FROM @T UNPIVOT(o FOR col IN(a,b,c,d,e,f))unpvt )他们究竟做了什么? – cMinor

+1

@darkcminor - 它将列结构转换成行(基本上和'NormalizedInputs'在另一个答案中一样,除了一次通过数据而不是6次)。如果你只运行'SELECT * FROM @T UNPIVOT(o for col IN(a,b,c,d,e,f))unpvt',应该清楚发生了什么。根据你对托马斯答案的看法,把你的基础数据放到这个表格中可能是最简单的,而不是试图使用动态列。 –

+0

好吧,我想你的解决方案更适合我的问题。但有一个额外的问题给你...是否有可能检测到案件x * y和y * x(例如a * b和b * a)是一样的,所以我避免再次计算它们? – cMinor

1
With Inputs As 
    (
    Select 1 As RowNum, 1.2 As a, 2.3 As b, 4.4 As c, 5.1 As d, 6.7 As e, 11.9 As f 
    Union All Select 2, 7.2, 2.3, 4.3, 5.1, 4.7, 3.9 
    Union All Select 3, 1.9, 5.3, 3.3, 5.1, 3.7, 8.9 
    Union All Select 4, 5.2, 2.7, 7.4, 9.1, 1.7, 2.9 
    ) 
    , NormalizedInputs As 
    (
    Select RowNum, 'a' As ColName, a As Value From Inputs 
    Union All Select RowNum, 'b', b From Inputs 
    Union All Select RowNum, 'c', c From Inputs 
    Union All Select RowNum, 'd', d From Inputs 
    Union All Select RowNum, 'e', e From Inputs 
    Union All Select RowNum, 'f', f From Inputs 
    ) 
Select N1.RowNum, Sqrt(Sum(N1.Value * N2.Value)) 
From NormalizedInputs As N1 
    Left Join NormalizedInputs As N2 
     On N2.RowNum = N1.RowNum 
      And N2.ColName >= N1.ColName 
Group By N1.RowNum 
+0

的副本好,但是如果有更多的列,你会怎么做?是否有更一般的方法来做到这一点? – cMinor

+0

我遇到的问题是可能会有超过60列...您提供的解决方案是正确的,但要使其一般? – cMinor

+1

@darkcminor - SQL不是为动态列生成而设计的,因此也没有机制。解决这个问题的唯一方法是静态写出列,或使用动态SQL。如果您要使用动态SQL,则不应该在T-SQL中执行。你应该在中间层组件中做到这一点。 – Thomas