1

一些 T-SQL 的帮助将不胜感激。

我有以下四个表:

  • 项目(ID)
  • ItemVersion(Id,FK 多对一 Item.Id)
  • ItemVersionStatusLog (LogDate, FK 多对一 ItemVersion.Id, FK 多对一 StatusType.Id)
  • 状态类型(ID、别名)

我只列出了适合这个问题的列。

根实体是一个Item. 对于每个Item,都有一个或多个ItemVersion条目。对于每个ItemVersion条目,有一个或多个ItemVersionStatusLog条目带有日期和对 a 的引用StatusType(例如,创建、更新、禁用)。

我想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 语句中做到这一点。我的主要目标是 SQL Server 2008,但也没有太多修改的 SQL Server Compact 4,所以依赖 UDF 不是一个很好的选择,但感谢任何帮助:)

更新 - 一些示例数据

Item:
Id
--
1
2

项目版本:

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

状态类型:

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

项目版本状态日志:

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 项的预期结果将是:

项目状态

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小提琴版本

上述解决方案的一个问题是它不允许在同一日期和时间为同一状态输入多个条目。如果我们可以假设在这种平局的情况下,将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 的情况下生活,您可以使用 GROUP BY:

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 回答