从许多行中选择最新属性

时间:2019-07-03 20:19:06

标签: sql sql-server

我有一个系统,该系统接收对表中数据的更新。更新的所有列都允许使用null,这意味着如果收到null,则任何旧值都应保持不变。

该表还包含数字列(称为值)和非数字列(称为属性)。

应该将值简单地添加在一起...但是对于属性,应该选择最新的更新。

真正的问题是仅仅获取所有属性的最新更新,但是我之所以包含values列,只是因为它是现实生活中的一部分。

该解决方案今天可以运行,但不是很稳定。它只是简单地一个接一个地处理更新,并确保以与到达它们相同的顺序对其进行读取。

不幸的是,有时这会导致大量的循环,因为一天中很容易有成千上万个不同的“到达时间”。 这意味着每次收到更新时,即使只有一行也是如此...我创建了一个全新的结果表,可能只有一个更改。

我希望这可以作为单个SQL运行,而不是在服务器外部进行很多循环。

另一个问题是值列和属性列的数量很多。 (总计70-100。)

我创建了一个SQL提琴,以解决该问题...但是我目前的最佳想法是使用交叉应用(我使用MSSQL Server 2017,所以这是可能的。)

sqlfiddle.com /#!18 / 0a8a9 / 2

(小提琴显示了一个示例,并在此过程中解释了一些其他内容。)

即使只有3行需要检查“最新”的示例,代码也无法控制。 如果要实现这一点,那将是完全无法管理的,而且我也不是很确定优化程序会如何看待这40-50个连接/应用。

如何实现? 作为单个SQL(允许很多CTE等)。 无需为每个属性添加很多行?

如果由于某些错误的设计而最终导致此问题,请也告诉我。尤其是在设计上稍作改动就可以解决问题。

1 个答案:

答案 0 :(得分:0)

尝试以下查询。请仔细检查语法。

;WITH cte_dates (ItemNumber, CorrectionTime_A1, CorrectionTime_A2, CorrectionTime_A3)
AS
(
  SELECT ItemNumber, 
    MAX(CASE WHEN Attribute1 IS NULL THEN NULL ELSE CorrectionTime END) AS  CorrectionTime_A1,
    MAX(CASE WHEN Attribute2 IS NULL THEN NULL ELSE CorrectionTime END) AS  CorrectionTime_A2,
    MAX(CASE WHEN Attribute3 IS NULL THEN NULL ELSE CorrectionTime END) AS  CorrectionTime_A3
  FROM Updates
  GROUP BY ItemNumber
)

SELECT u.ItemNumber,
  MAX(CASE WHEN u.CorrectionTime=m.CorrectionTime_A1 THEN Attribute1 ELSE NULL END) AS Attribute1,
  MAX(CASE WHEN u.CorrectionTime=m.CorrectionTime_A2 THEN Attribute2 ELSE NULL END) AS Attribute2,
  MAX(CASE WHEN u.CorrectionTime=m.CorrectionTime_A3 THEN Attribute3 ELSE NULL END) AS Attribute3,
  SUM(Value1) AS Value1,
  SUM(Value2) AS Value2,
  SUM(Value3) AS Value3
FROM cte_dates m
INNER JOIN Updates u
ON m.ItemNumber=u.ItemNumber
GROUP BY u.ItemNumber;