2016-09-19 7 views
6

上位n個のグループのレコードを選択します。n個のグループのすべてのレコードを選択するには?

テーブル 'ランナー':

id gid status rtime 
    --------------------------- 
    100 5550 1   2016-08-19 
    200 5550 2   2016-08-22 
    300 5550 1   2016-08-30 
    100 6050 3   2016-09-01 
    200 6050 1   2016-09-02 
    100 6250 1   2016-09-11 
    200 6250 1   2016-09-15 
    300 6250 3   2016-09-19 

テーブル '静的'

id description env 
    ------------------------------- 
    100 something 1 somewhere 1 
    200 something 2 somewhere 2 
    300 something 3 somewhere 3 

ユニットID(ID)がグループ内で一意であるが、その列内で一意でない私のデータは、このようになりますグループのインスタンスが定期的に生成されるためです。グループid(gid)はすべてのユニットに割り当てられますが、複数のインスタンスでは生成されません。

テーブルを結合してすべてを選択するか、特定の値でフィルタするのは簡単ですが、グループIDを直接参照せずに、たとえば最初の2つのグループのすべてのレコードを選択するにはどうすればよいですか? 期待される結果は次のようになります。

id gid description status rtime 
    -------------------------------------- 
    300 6250 something 2 3   2016-09-19 
    200 6250 something 1 1   2016-09-15 
    100 6250 something 3 1   2016-09-11 
    200 6050 something 2 1   2016-09-02 
    100 6050 something 1 3   2016-09-01 

エクストラ質問:私はこのようなタイムフレームをフィルタリングする場合:

[...] 
    WHERE runner.rtime BETWEEN '2016-08-25' AND '2016-09-16' 

確保する簡単な方法は、グループが切断されていないこと、ありますが、どちらかで表示されますすべてのレコードか全くないのですか?

+0

次の2つのクエリを必要とするだろう。これらの2つのグループIDを使用してこれらの2つのグループのすべてのレコードを取得する親クエリを作成します。 –

+0

SQL Serverのウィンドウ関数、ROW_NUMBER、NTILEなどを参照してください。 – SQLMason

答えて

0

これを行うにはROW_NUMBER()を使用できます。まず、グループをランク付けするクエリを作成します。

SELECT gid, ROW_NUMBER() over (order by gid desc) as RN 
FROM  Runner 
GROUP BY gid 

その後、あなたの他の情報を取得し、句は、あなたが見たいグループの数をフィルタリングするために使用する場所派生テーブルとしてこれを使用します。例えば、以下の上位5グループRN <= 5返します、:日付についてのあなたの2番目の質問について

SELECT  id, R.gid, description, status, rtime 
FROM  (SELECT gid, ROW_NUMBER() over (order by gid desc) as RN 
      FROM  Runner 
      GROUP BY gid) G 
INNER JOIN Runner R on R.gid = G.gid 
INNER JOIN Statis S on S.id = R.id 
WHERE  RN <= 5 --Change this to see more or less groups 

を、あなたはそのようなサブクエリでこれを行うことができます。

SELECT * 
FROM Runner 
WHERE gid IN (SELECT gid 
       FROM Runner 
       WHERE rtime BETWEEN '2016-08-25' AND '2016-09-16') 
+0

両方の質問に対して非常に良い答えです。ありがとうございました。 – Xen

1

Hmmm。私はこれがあなたが望むことをするかもしれないと思う:

select top (1) with ties r.* 
from runner r 
order by min(rtime) over (partition by gid), gid; 

少なくとも、これは完全な最初のグループを得るでしょう。

いずれの場合でも、にはgidをキーとして含めることと、top with tiesを使用することが考えられます。

1

を行うことができますここ
with report as(
select n.id,n.gid,m.description,n.status,n.rtime, dense_rank() over(order by gid desc) as RowNum 
from @table1 n 
inner join @table2 m on n.id = m.id) 

select id,gid,description,status,rtime 
from report 
where RowNum<=2 -- <-- here n=2 
order by gid desc,rtime desc 

作業demo

1

DENSE_RANKはここ

Select * From 
(
select DENSE_RANK() over (order by gid desc) as D_RN, r.* 
from runner r 
) A 
Where D_RN = 1 
+0

このソリューションは面白いです。 nグループのすべてのレコードを選択する問題を正確に解決するのではなく、特定のグループのすべてのレコードをオーダー番号で選択します。私もそれを使うことができるので、それに感謝します。 – Xen

0

理想的なソリューションランキング関数(ROW_NUMBERDENSE_RANKなど)を使用する必要はありませんように見えます。

SELECT r.id, gid, [description], [status], rtime 
FROM runner r 
INNER JOIN static s ON r.id = s.id 
WHERE gid IN (
    SELECT TOP 2 gid FROM runner GROUP BY gid ORDER BY gid DESC 
) 
ORDER BY rtime DESC; 

同じ使用してCTE

WITH grouped 
AS 
(
    SELECT TOP 2 gid 
    FROM runner GROUP BY gid ORDER BY gid DESC 
) 
SELECT r.id, grouped.gid, [description], [status], rtime 
FROM runner r 
INNER JOIN static s ON r.id = s.id 
INNER JOIN grouped ON r.gid = grouped.gid 
ORDER BY rtime DESC; 
関連する問題