1

SSMS 2008 を使用して、1 つの行/クライアントだけを選択しようとしています。次の列を選択する必要があります: client_nameend_date、およびprogram。一部のクライアントには、クライアント行が 1 つしかありません。しかし、他の人は複数持っています。

複数の行を持つクライアントの場合、通常は異なるend_dateとがありprogramます。例えば:

CLIENT       PROGRAM        END_DATE
a            b              c
a            d              e
a            f              g
h            d              e
h            f              NULL

これは、実際のデータの単純化されたバージョンです。ご覧のとおり、異なるクライアントが同じプログラム ("d") 内にある場合があります。ただし、同じクライアントが同じプログラムに複数回参加することはできません。

また、注意が必要なのは、end_dateが NULL になる可能性があることです。そのため、1 行を超えるクライアントを選択しようとしたときに、1 行を超える HAVING ステートメントを追加しました。しかし、これにより NULLEnd_date行がすべて削除されました。

要約すると、クライアントごとに 1 つの行が必要です。したがって、合計行が 1 つのみのクライアント + 上記のクライアントのうち、次の基準を持つクライアント:

  • End_dateが最大または NULLの行のみを選択します。(ほとんどの場合、end_dateこれらのクライアントでは は null です)。

できるだけ少ないロジックでこれを達成するにはどうすればよいですか?

4

1 に答える 1

4

ROW_NUMBER()SQL Server 2005以降では、共通テーブル式(CTE)をandPARTITION BY関数と組み合わせて使用​​できます。このCTEは、データを1つの基準で「パーティション化」します。この場合はClient、個別のクライアントごとに「パーティション化」を作成します。次にROW_NUMBER()、は別の基準で並べ替えられた各パーティションに番号を付けます(ここでは作成しましたDATETIME)。パーティションごとに個別に1から上の番号を割り当てます。

したがって、この場合、の順序DATETIME DESCで、最新の行に1の番号が付けられます。これは、CTEから選択するときに使用する事実です。ここで関数を使用ISNULL()して、NULLを持つ行にend_date任意の値を割り当て、「順番に取得」しました。あなたの質問を正しく理解したかどうかはよくわかりませんでした。特定の行よりもNULL行を選択しますか、それとも既存の値をNULLend_Dateよりも優先しますか?end_Date

これにより、各クライアント(データの「パーティション」ごと)の最新の行が選択されます。

DECLARE @clients TABLE (Client CHAR(1), Program CHAR(1), END_DATE DATETIME)

INSERT INTO @clients 
VALUES('a', 'b', '20090505'),
('a', 'd', '20100808'),
('a', 'f', '20110303'),
('h', 'd', '20090909'),
('h', 'f', NULL)

;WITH LatestData AS
(
   SELECT Client, Program, End_Date,
       ROW_NUMBER() OVER(PARTITION BY CLient ORDER BY ISNULL(End_Date, '99991231') DESC) AS 'RowNum'
    FROM @clients
)
SELECT Client, Program, End_Date
FROM LatestData 
WHERE RowNum = 1

結果は次のようになります。

Client  Program  End_Date
   a       f     2011-03-03
   h       f     (NULL)
于 2011-09-17T22:19:40.637 に答える