2013-03-25 11 views
5

あいまいなタイトルのため、申し訳ありませんが、検索方法や質問が不明です。複数の列の集計に基づいて1行を返す方法

 
RowID  FkId  Rank  Date 
ID1   A   1   2013-3-1 
ID2   A   2   2013-3-2 
ID3   A   2   2013-3-3 
ID4   B   3   2013-3-4 
ID5   A   1   2013-3-5 

私は、各FkIdのために1行を返しますビューを作成する必要があります。

は、私たちがTableAのを考えてみましょう。行は最大ランクと最大日付でなければなりません。したがって、FkId "A"の場合、クエリは "ID3"の行を返します。

サブクエリを使用して1行を返すことができました。最初に私はMAX(ランク)を得てから、FkId &ランクでMAX(日付)グループを取得する別のクエリに参加します。

 
SELECT TableA.* 
(Select FkId, MAX(Rank) AS Rank FROM TableA GROUP BY FkId) s1 
INNER JOIN (Select FkId, Rank, MAX(Date) AS Date FROM TableA GROUP BY FkId,Rank) s2 ON s1.FkId = s2.FkId AND s1.Rank = s2.Rank 
INNER JOIN TableA ON s2.FkId = TableA.FkId AND s2.Rank = TableA.Rank AND s2.Date = TableA.Date 

同じ結果が得られるより効率的なクエリがありますか?探してくれてありがとう。

編集:最後の答えからID5が追加されました。私が通常のMAX(ランク)、MAX(日付)GROUP BY FKIdを試してみたら、 "A"の場合はAを得ます。 2; 2013-3-5。この結果はRowIdまで一致しません。

+0

ランクのデータ型とは何ですか? –

+0

最大ランクのすべての行から最大日付の行?または、最大の日付を持つすべての行から最大ランクの行? (これら2つは異なる場合があります) –

+0

@AaronKurtzhals:数値 – csthopper

答えて

4

あなたはCTE(仮定SQLサーバー> = 2005)でROW_NUMBERを使用することができます。

WITH CTE AS 
(
    SELECT TableA.*, 
     RN = ROW_NUMBER() OVER (PARTITION BY FkId Order By Rank Desc, Date DESC) 
    FROM Table A 
) 
SELECT RowID,FkId, Rank,Date 
FROM CTE WHERE RN = 1 
+1

+1。ウィンドウ関数は素晴らしいです。 'FkId'、' Rank'、 'Date'の行が2つ以上ある可能性がある場合は、' ROW_NUMBER() 'の代わりに' RANK() 'を使用することもできます。 –

+0

@ypercube:すべての最大行が必要な場合は、 'DENSE_RANK'を使用します(ただし、最初の位置にギャップがないため、' RANK'もここで動作します)。しかしOPは、 "... return単一行 "となる。 –

+0

はい、しかし、彼には1つしかないという保証はないと彼は言っていませんでした。 –

2

質問(この回答にコメントで明らか)を要求:それぞれに対する単一の行はの行に対応し

  • 最大日付及びランク
  • 結果をFkId

    1. 元のデータ。

    最大日付と最大ランクが別々の行にあるような行のFkIdsがある場合は、これらの要件の少なくとも1つを緩和する必要があります。

    あなたが要件(3)リラックスして喜んでいる場合は、GROUP BYを使用することができます。

    SELECT FkId, MAX(Rank) AS Rank, Max(Date) AS Date 
    FROM TableA 
    GROUP BY FkId 
    

    コメントに余分な情報を与えられました。あなたは、各FkIdための最高ランクのエントリの、最新のを望んでいることを、次のように動作するはずです:

    SELECT FkId, Rank, MAX(Date) AS Date 
    FROM TableA A 
    WHERE Rank = (SELECT MAX(Rank) 
           FROM TableA sub 
           WHERE A.FkId = sub.FkId 
           GROUP BY sub.FkId) 
    GROUP BY FkId, Rank 
    

    はここsqlfiddle to show it in actionです。

  • +0

    'MAX(Rank)'と 'Max(Date)'は同じ行にないかもしれません! –

    +0

    ID1の日付が2013-3-5の場合はどうなりますか?このクエリは、RowIdまで一致しないA; 2; 2013-3-5を返します。 – csthopper

    +0

    それは公正な批評です。私は "あなたはその場合に何が起こると思いますか?"あなたは両方の行を必要としますか?私はそれの限界と問題の範囲を明確にするために私の答えを編集しました。 – Wilduck

    1

    あなたはそれを達成するためにランク()とインラインクエリを使用することができます。

    
    select * from TableA 
    where RowID in (
         select rowID from (
          select FKID, RowID, 
            rank() over (partition by FKID order by [Rank] desc, [Date] desc) as RankNumber 
            from TableA) A 
         where A.RankNumber=1) 
    

    SQL Fiddle Demo

    0

    また、卑劣なこととlike thisを示唆したものをljh達成することができます

    select top 1 with ties * 
    from TableA 
    order by rank() over (
        partition by FKID 
        order by [Rank] desc, [Date] desc 
    ) 
    
    関連する問題