web-dev-qa-db-ja.com

各カテゴリから上位10件のレコードを選択する方法

フィールドを持つテーブルがあります

Hour,
PathId,
Duration,
Event,
CellId,
Channel

50以上のCellIdがあります。各CellIdには4つのPathId(つまり、0、1、2、3)があります。各PathIdには多くのイベントと期間があります。次に、各CellIdの上位10レコード(各PathId)を表示します。

サンプルテーブル

SampleTable

サンプル出力

SampleOutput

4

派生テーブルで row_number() を使用します。 CellIDでパーティション分割し、仕様に基づいて順序を使用します。メインクエリでは、rnでフィルタリングして、カテゴリごとに上位10行を取得します。

select T.CellID,
       T.PathID,
       T.Duration
from (
     select T.CellID,
            T.PathID,
            T.Duration,
            row_number() over(partition by T.CellID order by T.Duration desc) as rn
     from dbo.YourTable as T
     ) as T
where T.rn <= 10;
14
Mikael Eriksson

CROSS APPLY を使用するのはどうですか。例:

USE tempdb
GO

SET NOCOUNT ON
GO

IF OBJECT_ID('#tmp') IS NOT NULL DROP TABLE #tmp
CREATE TABLE #tmp
(
    CellId      INT,
    PathId      INT,
    Duration    INT
)
GO

INSERT INTO #tmp VALUES
    ( 10, 1, 100 ),
    ( 10, 0, 120 ),
    ( 10, 2, 125 ),
    ( 10, 1, 111 ),
    ( 10, 0, 215 ),
    ( 10, 2, 22 ),
    ( 10, 0, 222 ),
    ( 10, 0, 55 ),
    ( 10, 1, 555 ),
    ( 10, 2, 58 ),
    ( 10, 0, 88 ),
    ( 10, 0, 9 ),
    ( 10, 2, 98 ),
    ( 10, 1, 55 ),
    ( 10, 2, 98 ),
    ( 10, 2, 74 ),
    ( 10, 0, 65 ),
    ( 10, 0, 66 ),
    ( 10, 1, 85 ),
    ( 10, 1, 37 ),
    ( 10, 1, 55 ),
    ( 11, 2, 11 ),
    ( 11, 0, 25 ),
    ( 11, 2, 69 ),
    ( 11, 0, 88 ),
    ( 11, 2, 54 ),
    ( 11, 0, 44 ),
    ( 11, 1, 22 ),
    ( 11, 0, 22 ),
    ( 11, 1, 55 ),
    ( 11, 1, 69 ),
    ( 11, 0, 55 ),
    ( 11, 1, 65 ),
    ( 11, 1, 65 ),
    ( 11, 0, 33 ),
    ( 11, 2, 35 )
GO


SELECT x.*
FROM ( SELECT DISTINCT cellId FROM #tmp ) c
    CROSS APPLY ( SELECT TOP 10 * FROM #tmp t WHERE c.cellId = t.cellId ) x
3
wBob