1

いくつかのT-SQLの助けをいただければ幸いです。

次の4つのテーブルがあります。

  • アイテム(Id)
  • ItemVersion(Id、FK多対1 Item.Id)
  • ItemVersionStatusLog(LogDate、FK多対1 ItemVersion.Id、FK多対1 StatusType.Id)
  • StatusType(Id、Alias)

この質問に適切な列のみをリストしました。

ルートエンティティはItemです。それぞれに対してItem、1つ以上のItemVersionエントリがあります。エントリごとに、日付とへの参照(作成、更新、無効化など)を含むItemVersion1つ以上のエントリがあります。ItemVersionStatusLogStatusType

Item新しいテーブル()に集計ビューを作成して、それぞれの「最新のステータス」を要約します。このビューItemStatusを埋め戻し、データが変更されたときに更新し続けます。StatusType集計により、アイテムとペアごとに、ログテーブルの最大日付のエントリが得られます 。それぞれのスナップショットを取得できるように、アイテムのStatusType最新のものを取得できます。ItemVersion

それを置く別の方法は手続き的です:

For each Item
- For each StatusType
- - List the ItemVersion Id with the maximum date from ItemVersionStatusLog given the correct StatusType

集計ビューまたはテーブルのターゲット列は次のとおりです。

Item Id, ItemVersion Id, Date (from ItemVersionStatus), StatusType Id

UDFを使用すればこれをかなりうまく行うことができますが、可能であれば、単一のSQLステートメントでこれを実行したいと思います。私の主なターゲットはSQLServer2008ですが、SQL Server Compact 4もあまり変更されていないため、UDFに依存することは良い選択肢ではありませんが、助けていただければ幸いです:)

更新-いくつかのサンプルデータ

Item:
Id
--
1
2

ItemVersion:

Id  | ItemId | Name
----------
1   | 1      | Apple
2   | 1      | Orange
3   | 1      | Plum
4   | 2      | Petrol
5   | 2      | Diesel
6   | 2      | LPG

StatusType:

Id  | Alias
-----------
1   | Created
2   | Approved
3   | Published
4   | Deleted

ItemVersionStatusLog:

Id  | ItemVersionId | StatusTypeId | Date
------------------------------------------
1   | 1             | 1            | 2012-01-01 00:00
2   | 1             | 4            | 2012-01-01 00:05
3   | 2             | 1            | 2012-01-01 00:10
4   | 2             | 3            | 2012-01-01 00:15
5   | 3             | 1            | 2012-01-01 00:20
6   | 3             | 3            | 2012-01-01 00:25

この場合、アイテム1の期待される結果は次のようになります。

ItemStatus

ItemId | ItemVersionId | Date             | StatusTypeId
--------------------------------------------------------
1      | 3             | 2012-01-01 00:20 | 1
1      | 3             | 2012-01-01 00:25 | 3
1      | 1             | 2012-01-01 00:05 | 4
4

2 に答える 2

4
With MostRecentStatus As
    (
    Select ItemVersionId, StatusTypeId, [Date]
        , Row_Number() Over ( Partition By StatusTypeId Order By [Date] Desc ) As Rnk
    From ItemVersionStatusLog As IVSL
    )
Select IV.ItemId, M.ItemVersionId, M.[Date], M.StatusTypeId
From MostRecentStatus As M
  Join ItemVersion As IV
    On IV.Id = M.ItemVersionId
Where Rnk = 1

SQLフィドルバージョン

CTEを使用しないバージョン:

Select IV.ItemId, IVSL.ItemVersionId, IVSL.[Date], IVSL.StatusTypeId
From ItemVersionStatusLog As IVSL
  Join (
      Select  IVSL2.StatusTypeId, Max([Date]) As [Date]
      From ItemVersionStatusLog As IVSL2
      Group By IVSL2.StatusTypeId
      ) As Z
    On Z.StatusTypeId = IVSL.StatusTypeId
      And Z.[Date] = IVSL.[Date]
  Join ItemVersion As IV
    On IV.Id = IVSL.ItemVersionId

SQLフィドルバージョン

上記の解決策の1つの欠点は、同じ日時に同じステータスの複数のエントリを許可しないことです。このような同点の場合、最後の値が使用されると想定できる場合はItemVersionStatusLog.Id、次のように調整します。

Select IV.ItemId, IVSL.ItemVersionId, IVSL.[Date], IVSL.StatusTypeId
From ItemVersionStatusLog As IVSL
  Join (
      Select IVSL1.StatusTypeId, IVSL1.[Date], Max(IVSL1.Id) As Id
      From ItemVersionStatusLog As IVSL1
        Join (
            Select  IVSL2.StatusTypeId, Max([Date]) As [Date]
            From ItemVersionStatusLog As IVSL2
            Group By IVSL2.StatusTypeId
            ) As Z
          On Z.StatusTypeId = IVSL1.StatusTypeId
            And Z.[Date] = IVSL1.[Date]
      Group By IVSL1.StatusTypeId, IVSL1.[Date]
      ) As MostRecentStatus
    On MostRecentStatus.Id = IVSL.Id
  Join ItemVersion As IV
    On IV.Id = IVSL.ItemVersionId

SQLフィドルバージョン

于 2012-05-06T15:45:29.223 に答える
0

ItemVersion.Idなしで生活できる場合は、GROUPBYを使用できます。

SELECT
  item.Id,
  MAX(log.LogDate) as LogDate,
  status.Id
FROM Item item
JOIN ItemVersion version ON item.Id = version.ItemId
JOIN ItemVersionStatusLog log ON version.Id = log.ItemVersionId
JOIN StatusType status ON log.StatusTypeId = status.Id
GROUP BY
  item.Id,
  status.Id
于 2012-05-06T15:41:04.240 に答える