我有一个13 columns
的表,一个类型为varchar(25)
的表,其余的类型为`int(保存一年中每个月的值)。
对于每一行,我想从top 6 int
中选择12 columns
值并计算这些值的平均值。
我知道如何从给定列中选择前n个,但是如何跨多个列进行操作?
答案 0 :(得分:4)
select ID,
(
select avg(C)
from (
select top(6) C
from (values(C1),(C2),(C3),(C4),(C5),(C6),(C7),
(C8),(C9),(C10),(C11),(C12)) as T(C)
order by C desc
) as T
) as C
from YourTable
对于SQL Server 2005,它看起来像这样,因为您无法使用Table Value Constructor
select ID,
(
select avg(C)
from (
select top(6) C
from (select C1 union all
select C2 union all
select C3 union all
select C4 union all
select C5 union all
select C6 union all
select C7 union all
select C8 union all
select C9 union all
select C10 union all
select C11 union all
select C12) as T(C)
order by C desc
) as T
) as C
from YourTable
对于SQL Server 2000,这可能适合您。
select T1.ID,
avg(C) as C
from (
select ID, C1 as C from YourTable union all
select ID, C2 from YourTable union all
select ID, C3 from YourTable union all
select ID, C4 from YourTable union all
select ID, C5 from YourTable union all
select ID, C6 from YourTable union all
select ID, C7 from YourTable union all
select ID, C8 from YourTable union all
select ID, C9 from YourTable union all
select ID, C10 from YourTable union all
select ID, C11 from YourTable union all
select ID, C12 from YourTable
) as T1
where (
select count(*)
from (
select ID, C1 as C from YourTable union all
select ID, C2 from YourTable union all
select ID, C3 from YourTable union all
select ID, C4 from YourTable union all
select ID, C5 from YourTable union all
select ID, C6 from YourTable union all
select ID, C7 from YourTable union all
select ID, C8 from YourTable union all
select ID, C9 from YourTable union all
select ID, C10 from YourTable union all
select ID, C11 from YourTable union all
select ID, C12 from YourTable
) as T2
where T1.ID = T2.ID and
T1.C <= T2.C
) <= 6
group by T1.ID
我不希望这会特别快。也许更好的选择是将中间结果存储在临时表中。
create table #T
(
ID varchar(25),
C int
)
insert into #T
select ID, C1 as C from YourTable union all
select ID, C2 from YourTable union all
select ID, C3 from YourTable union all
select ID, C4 from YourTable union all
select ID, C5 from YourTable union all
select ID, C6 from YourTable union all
select ID, C7 from YourTable union all
select ID, C8 from YourTable union all
select ID, C9 from YourTable union all
select ID, C10 from YourTable union all
select ID, C11 from YourTable union all
select ID, C12 from YourTable
select T1.ID,
avg(C) as C
from #T as T1
where (
select count(*)
from #T as T2
where T1.ID = T2.ID and
T1.C <= T2.C
) <= 6
group by T1.ID
drop table #T
答案 1 :(得分:0)
首先,重要的是要理解将TOP与聚合结合使用不会限制聚合,而是限制结果集。看看这个例子:
SELECT TOP 2 SUM(col) FROM
(SELECT 1 AS col
UNION
SELECT 2
UNION
SELECT 3)sq
结果仍是“6”。
其次,聚合不适用于列,只能行。您需要手动评估它们。可能最有效的方法是从行创建一个表格,如下所示:
SELECT
(SELECT MAX(myval) FROM (values (col1), (col2), (col3), (col4)) as all_values(myval))
FROM (SELECT 1 as col1, 2 as col2, 3 as col3, 4 as col4)sq
答案 2 :(得分:0)
如果您使用的是SQL Server 2005或更高版本,则可以unpivot
table
,然后rank
值,最后计算averages
top 6 values
} identifier
。
类似的东西:
;WITH UnPivoted AS (
SELECT pk, MonthID, MonthNumber, MonthValue
FROM
(SELECT pk, Month1, Month2, Month3, Month4, Month5, Month6, Month7, Month8, Month9, Month10, Month11, Month12
FROM pvt) p
UNPIVOT
(pk FOR MonthNumber IN
(Month1, Month2, Month3, Month4, Month5, Month6, Month7, Month8, Month9, Month10, Month11, Month12)
)AS unpvt
),
UnPivotedRanked AS (
SELECT pk, MonthValue, RANK() OVER(PARTITION BY pk ORDER BY MonthValue DESC) AS pkRanked
FROM UnPivoted
GROUP BY pk
)
SELECT pk, AVG(MonthValue) AS Top6Average
FROM UnPivotedRanked
WHERE pkRanked < 6
GROUP BY pk