我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"。我不想从选择中选择这种语句进行选择。我更喜欢一些SQL函数。也许ROW_NUMBER是个好主意,但我不知道在这种情况下如何应用它。
答案 0 :(得分: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
(已更新,包含订单)
答案 1 :(得分: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
答案 2 :(得分:2)
我认为最直接的方法是使用row_number()
枚举行然后重新创建它们:
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);
编辑(基于修订后的问题):
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
按总计按升序保存记录。
答案 3 :(得分: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;
答案 4 :(得分:-2)
我不确定如何在SQLServer中使用“first”和skip子句 但在firebird中这有效,但我认为它可以修改为在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"