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 from a select を実行したくありません。私はいくつかのSQL関数をもっと探しています。ROW_NUMBER は良い考えかもしれませんが、この場合に正確に適用する方法がわかりません。

4

5 に答える 5

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
于 2013-08-30T19:59:50.573 に答える
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には、合計の昇順でレコードが保持されます。

于 2013-08-30T20:20:24.883 に答える
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;

SQLフィドル

于 2013-08-30T20:27:12.917 に答える
-2

"first" 句と skip 句を SQLServer でどのように使用すればよいかわかりませんが、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"
于 2013-08-30T19:58:06.063 に答える