2

我有一个表13 columns,其中一个带有类型varchar(25),其余的带有 `int 类型(保存一年中每个月的值)。

对于每一行,我想从中选择top 6 int12 columns并计算这些值的平均值。

我知道如何从给定列中选择前 n 列,但是如何跨多个列呢?

4

3 回答 3

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小提琴

对于 SQL Server 2005,它看起来像这样,因为您不能使用表值构造函数

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小提琴

对于 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

SQL小提琴

我不希望这会特别快。也许更好的选择是将中间结果存储在临时表中。

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
于 2013-08-19T19:28:48.097 回答
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
于 2013-08-19T18:43:10.703 回答
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
于 2013-08-19T18:52:22.130 回答