2013-08-30 46 views
2

的总和后,我ORDER BY cnt DESC我的结果是显示前三名值以及所有其他值

fld1 cnt 
A  9 
E  8 
D  6 
C  2 
B  2 
F  1 

我需要有前3显示,剩下的将被归纳为“其他”,像这样:

fld1 cnt 
A  9 
E  8 
D  6 
other 5 

编辑:

谢谢大家对您的输入。如果你看到实际陈述,可能会有所帮助:

SELECT 
    CAST(u.FA AS VARCHAR(300)) AS FA, 
    COUNT(*) AS Total, 
    COUNT(CASE WHEN r.RT IN (1,11,12,17) THEN r.RT END) AS Jr, 
    COUNT(CASE WHEN r.RT IN (3,4,13) THEN r.RT END) AS Bk, 
    COUNT(CASE WHEN r.RT NOT IN (1,11,12,17,3,4,13) THEN r.RT END) AS Other 
FROM R r 
    INNER JOIN DB..RTL rt 
    ON r.RT = rt.RTID 
    INNER JOIN U u 
    ON r.UID = u.UID 
WHERE rt.LC = 'en' 
GROUP BY CAST(u.FA AS VARCHAR(300))--FA is ntext 
ORDER BY Total DESC 

产生的结果有19条记录。我需要显示前5名并将其余的总结为“其他FA”。我不想通过这种语句从select中进行选择。我更期待一些SQL函数。也许ROW_NUMBER是个好主意,但我不知道如何在这种情况下应用它。

+0

您可能需要在接受的解决方案看这里:http://stackoverflow.com/questions/14478361/sum-with-sql -server-rollup-but-only-last-summary –

+0

@ PM77-1否。该问题不同。 –

+0

你的结果集有2个字段,你的查询有5个字段,而非1的字段出现在另一个字段中:P所以我不确定两者之间的关系现在... – funkwurm

回答

2

我认为最直接的方法是使用row_number()枚举行,然后reaggreate他们:

select (case when seqnum <= 3 then fld1 else 'Other' end) as fld1, 
     sum(cnt) as cnt 
from (select t.*, row_number() over (partition by fld1 order by cnt desc) as seqnum 
     from t 
    ) t 
group by (case when seqnum <= 3 then fld1 else 'Other' end); 

实际上,你可以这样做,因为你原来的一部分聚集,以及:

select (case when seqnum <= 3 then fld1 else 'Other' end) as fld1, 
     sum(cnt) as cnt 
from (select fld1, sum(...) as cnt, 
      row_number() over (partition by fld1 order by sum(...) desc) as seqnum 
     from t 
     group by fld1 
    ) t 
group by (case when seqnum <= 3 then fld1 else 'Other' end); 

EDIT(基于修订的问题):

select (case when seqnum <= 3 then FA else 'Other' end) as FA, 
     sum(Total) as Total 
from (SELECT CAST(u.FA AS VARCHAR(300)) AS FA, 
      COUNT(*) AS Total, 
      ROW_NUMBER() over (PARTITION BY CAST(u.FA AS VARCHAR(300)) order by COUNT(*) desc 
           ) as seqnum 
     FROM R r 
      INNER JOIN DB..RTL rt 
      ON r.RT = rt.RTID 
      INNER JOIN U u 
      ON r.UID = u.UID 
     WHERE rt.LC = 'en' 
     GROUP BY CAST(u.FA AS VARCHAR(300))--FA is ntext 
    ) t 
group by (case when seqnum <= 3 then FA else 'Other' end) 
order by max(seqnum) desc; 

最后的order by将记录按总数升序排列。

+0

请参阅我的编辑。你能帮我将ROW_NUMBER()放入该语句中吗?谢谢。 – chibis

+0

你的声明中没有叫'fld1' –

+0

这只是一个示例:)。 FA是fld1,Total是cnt – chibis

-2

我真的不知道如何“第一”,并跳过条款应在SQLServer的 使用,但在火鸟这个工作,但我认为这可能进行修改,以对SQLServer的

select first 3 p.fld1,p.cnt from Table p 
    union 
    select t."others",sum(t.cnt) from (
    select skip 3 'others' as "others",p.cnt from Table p 
    ) as t 
    group by "others" 
+1

-1中的前5名:“可以修改”显然不是正确的答案。 – Hogan

2
DECLARE @MyTable TABLE 
(
    fld1 VARCHAR(50) NOT NULL, 
    cnt INT NOT NULL 
); 
INSERT INTO @MyTable (fld1, cnt) 
VALUES 
('A', 9), ('E', 8), ('D', 6), 
('C', 2), ('B', 2), ('F', 1); 

SELECT ISNULL(z.new_fld1,'other') AS new_fld1, 
     SUM(z.cnt) AS sum_of_cnt 
     --,MAX(z.sort_cryteria) 
FROM 
(
    SELECT y.cnt, 
      -- I assume that `fld1` column is MANDATORY (NOT NULL) ! 
      CASE WHEN y.RowNum < 4 THEN fld1 ELSE NULL END AS new_fld1, 
      CASE WHEN y.RowNum < 4 THEN y.RowNum ELSE 4 END AS sort_cryteria 
    FROM 
    (
     SELECT *, ROW_NUMBER() OVER(ORDER BY x.cnt DESC) AS RowNum 
     FROM @MyTable x 
    ) y 
) z 
GROUP BY z.new_fld1 
ORDER BY MAX(z.sort_cryteria); 

运行结果:

new_fld1 sum_of_cnt sort_cryteria 
-------- ----------- ------------- 
A  9   1 
E  8   2 
D  6   3 
NULL  5   4 
+1

+1,_though_,选择列表中有'isnull'的原因是什么? (你可能在'case'中做'else''end') –

+0

好问题。 'fld1'可能包含'other'值,它可能具有最大的'cnt'值。在这种情况下,如果我使用'CASE当RowNum <4那么fld1 ELSE'其他'END'结果将是错误的,因为正确的结果将是(按此顺序):'其他','E','D','其他'(所有其他fld1值 - 其他分支)。 –

3

可能是这样的:

select top 3 fld1, cnt from mytable 
union 
select 'Z - Other', sum(cnt) from mytable 
where fld1 not in (select top 3 fld1 from mytable order by fld1) 
order by fld1 

(更新以包括顺序)

+0

+1超级简洁! –

+3

顶部3没有排序,我不知道.. –

+0

是的,想到这一点,但保持与OP结构。我也会添加ORDER BY –

0

你可以尝试这样的事:

select fld1,cnt from test 
where cnt in(select top 3 cnt from test) 
union 
select 'Other', sum(cnt)from test 
where cnt not in (select top 3 cnt from test) 
order by cnt desc; 

SQLFiddle

相关问题