SQLServer 2008 R 2でCross applyを使って最新のデータと最近のデータを統計します。


APPLY演算子を使用すると、クエリー動作を行う外部表式に戻ってくる行ごとに表値関数を呼び出すことができます。表の値関数を右入力とし、外部表式を左入力とします。左入力の各行の計算結果は、右入力の値を求めることによって得られ、生成された行は最終出力として結合される。APPLY演算子が生成した列のリストは、左入力の列のセットであり、後に右入力の列のリストが入力されます。
注意:APPLYを使用するには、データベース互換レベルは少なくとも90である必要があります。
APPLYにはCROSS APPLYとOUTER APPLYの2種類があります。CROSS APPLYは、外部テーブルに表の値関数で結果セットを生成する行のみを返します。OUTER APPLYは、結果セットを生成する行と、結果セットを生成しない行とを返します。ここで、表値関数が生成する列の値はNULLです。
久しぶりにSQLを書いて、手がちょっと生っぽいです。今日は質問に答えます。ついでにメモしておきます。

当事者のニーズ

問題は最新のデータと次のデータを一行に入れて表示することです。
重複した状況はどのように処理するかを説明していません。つまり、最新のデータが複数あるか、あるいは複数の新しいデータがあるかということですので、私は過多な処理をしていません。

--by wls
--
--       
--       
USE tempdb
GO
IF OBJECT_ID('t_TestbyWLS','U') IS NOT NULL
DROP TABLE t_TestbyWLS
GO
CREATE TABLE t_TestbyWLS(PName NVARCHAR(),PSId INTEGER,ChkDate NVARCHAR(),Price FLOAT)
GO
INSERT INTO t_TestbyWLS VALUES
('A',,'',.)
,('B',,'',.)
--,('B',,'',.)
,('A',,'',.)
,('B',,'',.)
,('A',,'',.)
--,('A',,'',.)
GO
SELECT * FROM t_TestbyWLS
GO
/*
SELECT PName,PSId,ChkDate,Price,DENSE_RANK() OVER(PARTITION BY PName ORDER BY CAST(Chkdate AS INTEGER) DESC ) AS DRID,
ROW_NUMBER() OVER(PARTITION BY PName ORDER BY CAST(Chkdate AS INTEGER) DESC,Price DESC ) AS RID
FROM t_TestbyWLS
GO
*/
WITH TempChkDate
AS
(
SELECT PName,PSId,ChkDate,Price,DENSE_RANK() OVER(PARTITION BY PName ORDER BY CAST(Chkdate AS INTEGER) DESC ) AS DRID,
ROW_NUMBER() OVER(PARTITION BY PName ORDER BY CAST(Chkdate AS INTEGER) DESC,Price DESC ) AS RID
FROM t_TestbyWLS
)
SELECT tcd.PName,tcd.PSID,tcd.ChkDate,tcd.Price,/*tcd.DRID,tcd.RID,*/t.tcd,t.tp
FROM TempChkDate AS tcd CROSS APPLY(SELECT ChkDate AS tcd, Price AS tp 
FROM TempChkDate
WHERE 
--tcd.DRID= AND
tcd.PName=TempChkDate.PName AND
tcd.PSId=TempChkDate.PSId AND
TempChkDate.Drid= 
) AS t
WHERE tcd.DRID=
GO 
運行の結果は正しいはずです。
しかし、実行計画を見ると、よくないですね。

時間があったらまた変えます。
これを試してみてもいいです。結果を見てください。
この原因はあなたが具体的な規定をしていないからです。

--by wls
--
--       
--       
------------------------------------------------------------------------
--         ,       。
--                 。
------------------------------------------------------------------------
USE tempdb
GO
IF OBJECT_ID('t_TestbyWLS','U') IS NOT NULL
DROP TABLE t_TestbyWLS
GO
CREATE TABLE t_TestbyWLS(PName NVARCHAR(),PSId INTEGER,ChkDate NVARCHAR(),Price FLOAT)
GO
INSERT INTO t_TestbyWLS VALUES
('A',,'',.)
,('B',,'',.)
,('B',,'',.)
,('A',,'',.)
,('B',,'',.)
,('A',,'',.)
,('A',,'',.)
GO
WITH TempChkDate
AS
(
SELECT PName,PSId,ChkDate,Price,DENSE_RANK() OVER(PARTITION BY PName ORDER BY CAST(Chkdate AS INTEGER) DESC ) AS DRID,
ROW_NUMBER() OVER(PARTITION BY PName ORDER BY CAST(Chkdate AS INTEGER) DESC,Price DESC ) AS RID
FROM t_TestbyWLS
)
SELECT tcd.PName,tcd.PSID,tcd.ChkDate,tcd.Price,tcd.DRID,tcd.RID,t.tcd,t.tp
FROM TempChkDate AS tcd 
CROSS APPLY(SELECT ChkDate AS tcd, Price AS tp 
FROM TempChkDate
WHERE 
--tcd.DRID= AND
tcd.PName=TempChkDate.PName AND
tcd.PSId=TempChkDate.PSId AND
TempChkDate.Drid= 
) AS t
WHERE tcd.DRID=
GO
以上の内容は小编でご绍介したSQLServer 2008 R 2でCross applyを使って最新データと最近のデータに関する知识です。