4

我有一个 SQL Server 表,其中包含与各种 s 相关Measurement的几个不同s 的增量s:AttributeObject

MeasurementID  ObjectID    Attribute1  Attribute2  Attribute3
100            1           'blue'      111         'large'
101            1           'blue'      114         'large'
102            1           'red'       114         'large'
103            1           'red'       117         'large'
104            1           'cyan'      118         'large'
105            2           'blue'      450         'huge'
106            3           'blue'      450         'huge'
107            3           'red'       450         'huge'

我的目标是找到一个有效的查询,给定一个特定的ObjectID告诉我哪些属性更改以及何时更改。例如,假设ObjectID=1. Attribute1MeasurementID=102(from 'blue'to 'red') 发生变化,对于Attribute2atMeasurementID=101MeasurementID=103以及Attribute3在任何时候 ( NULL) 也是如此。从概念上讲,我正在寻找满足这个伪代码定义的东西:

CREATE FUNCTION GetMeasurementChanges (ObjectID int, AttributeName varchar)
RETURNS @returnMeasurementIDs TABLE
  (MeasurementID int) -- rows of MeasurementIDs 

我可以想出一种缓慢的方法,通过逐个选择临时表ObjectObject然后遍历行,测试每个行Attribute,但我怀疑这会表现得很糟糕。

任何人有一个技巧或类似的问题,他们可以指出我吗?

谢谢!

4

4 回答 4

3

尝试这个

if (@attributeName = 'Attribute1')
begin
  insert into @returnMeasurementIDs
  select measurementid from (
  select measurementid,
  rank() over (partition by objectId, attribute1 order by measurementid) rnk,
  row_number() over (order by measurementid) rn
  from table where objectid = @ObjectID
  ) v where rnk = 1 and rn <> 1
end
else if (@attributeName = 'Attribute2')
begin
  insert into @returnMeasurementIDs
  select measurementid from (
  select measurementid,
  rank() over (partition by objectId, attribute2 order by measurementid) rnk,
  row_number() over (order by measurementid) rn
  from table where objectid = @ObjectID
  ) v where rnk = 1 and rn <> 1
end
else if (@attributeName = 'Attribute3')
begin
  insert into @returnMeasurementIDs
  select measurementid from (
  select measurementid,
  rank() over (partition by objectId, attribute3 order by measurementid) rnk,
  row_number() over (order by measurementid) rn
  from table where objectid = @ObjectID
  ) v where rnk = 1 and rn <> 1
end

SQL 演示

Rank - 用于按 objectid 和属性对每个组进行排名,当属性更改时它将返回 1。

Row_Number用于对所有行进行排名并忽略所有更改的测量 ID 列表中的第一行,以便返回第 102、104 行等。

于 2013-04-19T02:11:34.183 回答
1
CREATE FUNCTION dbo.GetMeasurementChanges -- always use schema prefix
(
  @ObjectID INT, @AttributeName VARCHAR(32)
)
RETURNS TABLE -- use an inline table-valued function when possible
WITH SCHEMABINDING
AS
  RETURN 
  (
    WITH x AS 
    (
      SELECT ObjectID, MeasurementID, Attribute1, Attribute2, Attribute3, 
        rn = ROW_NUMBER() OVER (ORDER BY MeasurementID)
      FROM dbo.MyTable -- update this of course
      WHERE ObjectID = @ObjectID
    ), y AS 
    (
      SELECT MeasurementID,
        r1 = CASE @AttributeName WHEN 'Attribute1' THEN ROW_NUMBER() 
             OVER (PARTITION BY Attribute1 ORDER BY MeasurementID) END,
        r2 = CASE @AttributeName WHEN 'Attribute2' THEN ROW_NUMBER() 
             OVER (PARTITION BY Attribute2 ORDER BY MeasurementID) END,
        r3 = CASE @AttributeName WHEN 'Attribute3' THEN ROW_NUMBER() 
             OVER (PARTITION BY Attribute3 ORDER BY MeasurementID) END
      FROM x
    )
    SELECT MeasurementID FROM y WHERE 1 IN (r1, r2, r3)
      AND NOT EXISTS 
      (
        SELECT 1 FROM x WHERE x.rn = 1 
        AND MeasurementID = y.MeasurementID
      )
  );
GO

替代:

CREATE FUNCTION dbo.GetMeasurementChanges -- always use schema prefix
(
  @ObjectID INT, 
  @AttributeName VARCHAR(32)
)
RETURNS TABLE -- use an inline table-valued function when possible
WITH SCHEMABINDING
AS
  RETURN 
  (
    WITH x AS 
    (
      SELECT ObjectID, MeasurementID, Attribute1, Attribute2, Attribute3, 
        rn = ROW_NUMBER() OVER (ORDER BY MeasurementID)
      FROM dbo.MyTable WHERE ObjectID = @ObjectID
    ),
    y AS 
    (
      SELECT MeasurementID, r = ROW_NUMBER() OVER (
            PARTITION BY CASE @AttributeName 
          WHEN 'Attribute1' THEN Attribute1
          WHEN 'Attribute2' THEN CONVERT(VARCHAR(32), Attribute2)
          WHEN 'Attribute3' THEN Attribute3 END 
        ORDER BY MeasurementID)
      FROM x
    )
    SELECT MeasurementID FROM y WHERE r = 1
      AND NOT EXISTS 
      (
        SELECT 1 FROM x WHERE x.rn = 1 
        AND MeasurementID = y.MeasurementID
      )
  );
GO
于 2013-04-19T03:11:54.790 回答
0

尝试这个

SELECT  CASE WHEN a.Attribute1 = b.Attribute1 THEN 1 END AS Attribute1,
    CASE WHEN a.Attribute2 = b.Attribute2 THEN 1 END AS Attribute2,
    CASE WHEN a.Attribute3 = b.Attribute3 THEN 1 END AS Attribute3
FROM    Measurements a
    INNER JOIN Measurements b
    ON (b.MeasurementID = (SELECT MAX(MeasurementID) FROM Measurements c WHERE    c.MeasurementID < a.MeasurementID AND c.ObjectID = a.ObjectID))
于 2013-04-19T07:17:25.117 回答
0

将选项与 TOP 1 + CROSS APPLY运算符一起使用

CREATE FUNCTION dbo.getMeasurementChanges(@ObjectID int, @AttributeName nvarchar(10))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
 (
  SELECT o.MeasurementID
  FROM dbo.test90 t 
    CROSS APPLY (
                 SELECT TOP 1 MeasurementID, ObjectID,
                   CASE @AttributeName WHEN 'Attribute1' THEN t.Attribute1
                                       WHEN 'Attribute2' THEN CAST(t.Attribute2 AS nvarchar(10))
                                       WHEN 'Attribute3' THEN t.Attribute3 END AS t1Attributes,
                   CASE @AttributeName WHEN 'Attribute1' THEN t2.Attribute1
                                       WHEN 'Attribute2' THEN CAST(t2.Attribute2 AS nvarchar(10))
                                       WHEN 'Attribute3' THEN t2.Attribute3 END AS t2Attributes
                 FROM dbo.test90 t2
                 WHERE t2.ObjectID = @ObjectID AND t.MeasurementID < t2.MeasurementID                                      
                 ORDER BY MeasurementID ASC
                 ) o
WHERE t.ObjectID = @ObjectID AND t1Attributes != t2Attributes)

为了提高性能,请使用以下索引:

CREATE INDEX x ON dbo.test90(ObjectID) INCLUDE(MeasurementID, Attribute1, Attribute2, Attribute3)
CREATE INDEX x2 ON dbo.test90(MeasurementID) INCLUDE(ObjectID, Attribute1, Attribute2, Attribute3)

SQLFiddle上的演示

于 2013-04-19T08:36:59.943 回答