3

次の構造を持つ CampRegistration というテーブルがあります。

[EID] INT, [CampName] VARCHAR(100), [StartDt] DATETIME

EID は、キャンプに参加した人の識別子です。CampRegistration テーブル内の各人が特定の日付より前に参加した最後のキャンプを選択したいと考えています。

これが私の最初の試みでした:

@DECLARE @currentCampDt DATETIME = '2012-8-4';
SELECT [EID], [CampName], MAX([StartDt]) [StartDt]
FROM [CampRegistration]
WHERE [StartDt] < @currentCampDt 
GROUP BY [EID],[CampName]
order by [EID]

ここでの問題は、誰かが異なる名前で複数のキャンプに参加した場合、その人に対して複数の結果が得られることです (各キャンプ名の最後に参加したもの)。私は、参加者が最後に参加したキャンプの記録を 1 人につき 1 つだけ取得したいと考えています。最終的には、各レコード (EID、CampName、およびキャンプの StartDt) についてこれら 3 つの情報を取得する必要があるため、実際に から CampName を削除できるかどうかはわかりませんGroup By

私は SQL Server 2012 を使用していますが、このタイプのクエリ結果を実装する方法についての提案をいただければ幸いです。

ありがとう。

4

3 に答える 3

5

1 つのアプローチは、CTE (Common Table Expression) を使用することです。

この CTE を使用すると、データをいくつかの基準 (つまり、独自の基準) でパーティション分割し、EIDSQL Server ですべての行に番号を付けて、これらの「パーティション」ごとに 1 から開始し、いくつかの基準で並べ替えることができます。

だから、次のようなことを試してください:

;WITH CampEvents AS
(
   SELECT 
       EID, CampName, StartDt,
       RowNum = ROW_NUMBER() OVER(PARTITION BY EID ORDER BY StartDt DESC)
   FROM 
       dbo.CampRegistration
)
SELECT 
   EID, CampName, StartDt
FROM 
   CampEvents
WHERE
   RowNum = 1

ここでは、各「パーティション」(つまり、各EID) の「最初の」エントリのみを選択しています (降順で並べられています)。StartDtそのため、最新の最新のイベントはRowNum = 1.

それはあなたが探しているものに近づきますか??

于 2013-01-05T09:24:06.427 に答える
2

これは高速ではありませんが、それを行います:

@DECLARE @currentCampDt DATETIME = '2012-8-4';

SELECT o.[EID], o.[CampName], o.[StartDt]
FROM [CampRegistration] o
WHERE o.[StartDt] = ( 
                      SELECT MAX(i.[StartDt]) 
                      FROM [CampRegistration] i WHERE i.[StartDt] < @currentCampDt
                      AND
                      i.[EID] = o.[EID]
                    )
order by o.[EID]
于 2013-01-05T09:23:58.630 に答える
1

あなたはこれを行うことができます:

WITH LastCampsAttended
As
(
  SELECT *,
    ROW_NUMBER() OVER(PARTITION BY EID ORDER BY StartDt DESC) AS rownum
  FROM CampRegistration
  WHERE [StartDt] < @currentCampDt 
)
SELECT 
  EID,
  CampName,
  StartDt
FROM LastCampsAttended
WHERE rownum = 1;

SQL フィドルのデモ

または:

SELECT
  camps.*
FROM CampRegistration camps
INNER JOIN 
(
  SELECT EID, MAX(StartDt) LatestDate
  FROM CampRegistration
  GROUP BY EID
) LatestCamps  ON camps.EID = LatestCamps.EID
              AND camps.StartDt = LatestCamps.LatestDate
WHERE camps.StartDt < @currentCampDt ;

更新された SQL フィドルのデモ

于 2013-01-05T09:23:18.567 に答える