2013-06-21 47 views
2

我有这个疑问:SQL Server 2005中的价值观差异

SELECT ID, Value 
FROM Table 
WHERE ID = (SELECT MIN(ID) FROM Table WHERE RecID = 12637) 

UNION 

SELECT ID, Value 
FROM Table 
WHERE ID = (SELECT MAX(ID) FROM Table WHERE RecID = 12637) 

我想这是我跳水这两个值结果之间的差异。但我也需要它,只有这样做时,如果ID不同 - 我相信这不会是一个问题,因为我相信如果只有一条记录,只返回1个结果。

更新

ID | Value 
------------ 
100 | 23000 
110 | 25000 

当前查询结果如上所示。我正在寻找一种方法来获得2000年的结果。

背后的故事我有一个表格可以捕获每个条目的值。可能有1条记录或15条后续修订。我想知道什么之间的第一条记录MIN(ID)和最新记录MAX(ID)

+0

因此,对于每个RecID,您想要第一个修订版本和最后一个修订版本?那么,知道如何获得第一个和最后一个,那么你想要得到他们之间的区别? – billinkc

+0

这是正确的,billinkc。 感谢marc_s清理格式。我的第一个问题仍然试图找出正确的方式来使用它。 – wildwally

+0

“ID”和“VALUE”的数据类型是什么? –

回答

3

如果IDVALUEINT NOT NULL再一个办法是

SELECT RecID, 
     CAST(SUBSTRING(MAX(B), 6, 4) AS INT) - CAST(SUBSTRING(MIN(B), 6, 4) AS INT) 
FROM YourTable 
     CROSS APPLY (SELECT CASE 
          WHEN ID < 0 THEN 0x00 
          ELSE 0x01 
          END + CAST(ID AS BINARY(4)) + CAST(VALUE AS BINARY(4))) CA(B) 
GROUP BY RecID 

或可替代另一种方式(少隐蔽和更强大的不断变化的数据类型)是

;WITH T AS 
(
SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY RecID ORDER BY ID ASC) RnAsc, 
     ROW_NUMBER() OVER (PARTITION BY RecID ORDER BY ID DESC) RnDesc 
FROM YourTable  
) 
SELECT MAX(CASE WHEN RnDesc = 1 THEN Value END) - MAX(CASE WHEN RnAsc = 1 THEN Value END) 
FROM T 
WHERE 1 IN (RnAsc, RnDesc) 
GROUP BY RecID 

或者另一种方式,@Andriy的效率比效率更高一个,因为它避免了排序操作是

;WITH T AS 
(
SELECT *, 
     MIN(ID) OVER (PARTITION BY RecID) MinId, 
     MAX(ID) OVER (PARTITION BY RecID) MaxId 
FROM YourTable  
) 
SELECT MAX(CASE WHEN Id = MaxId THEN Value END) - MAX(CASE WHEN Id = MinId THEN Value END) 
FROM T 
GROUP BY RecID 
+0

替代方案非常干净,效果很好。 – wildwally

+0

@wildwally - 谢谢。 “更脏”的第一个可能会更有效率,但我不确定我是否真的会使用它。 –

+0

我一直怀疑(并不确定如何验证):如果有'ID ASC'上的索引,'ORDER BY ID DESC'和'ORDER BY ID ASC'一样是否会受益? (或者问题是否有意义?) –

-2

你的要求不是很清楚,我是第一个报道的差异,但你可以用做一套减法EXCEPT

+3

你能详细解答这个问题吗?这似乎更像是一个评论,然后是一个实际的答案。 – Taryn

1

有可能这是一个更优雅的方式,但我认为我有一个方法。我找到了第一行和最后一行,并将结果加在一起做出一行,然后进行数学计算。在只有一排的情况下,我不是100%确定你想要什么。我将它作为一个左外连接,以允许某些内容存在于分钟中,而不是最大值,然后作为连接条件的一部分,我排除了匹配的ID。如果这不是正确的,那么掐断了AND MN.ID <> MX.ID线

CREATE TABLE #tmp 
(
    ID int IDENTITY(1,1) NOT NULL 
, RecID int NOT NULL 
, Value int NOT NULL 
); 

INSERT INTO 
    #tmp 
(
    RecID 
, Value 
) 
SELECT 
    AC.object_id AS RecID 
, AC.precision + AC.scale AS Value 
FROM 
    sys.all_columns AS AC; 


WITH MINS AS 
(
    -- Find the first value for all the recids 
    SELECT 
     T.RecID 
    , T.Value 
    , T.ID 
    FROM 
     #tmp T 
    WHERE 
     T.ID = 
     (
      SELECT MIN(TI.ID) AS FirstID 
      FROM #tmp TI 
      WHERE TI.RecID = T.RecID 
     ) 
) 
, MAXS AS 
(
    -- Find the last value for all the recids 
    SELECT 
     T.RecID 
    , T.Value 
    , T.ID 
    FROM 
     #tmp T 
    WHERE 
     T.ID = 
     (
      SELECT MAX(TI.ID) AS FirstID 
      FROM #tmp TI 
      WHERE TI.RecID = T.RecID 
     ) 
) 
SELECT 
    MN.RecID 
, MN.Value - COALESCE(MX.Value, 0) AS Delta 
, MN.ID AS FirstID 
    -- might not exist 
, MX.ID AS LastID 
FROM 
    MINS AS MN 
    -- Assume we don't want things that were never updated 
    LEFT OUTER JOIN 
     MAXS AS MX 
     ON MN.RecID = MX.RecID 
     AND MN.ID <> MX.ID 
; 
+0

谢谢,正如您所指出的那样进行了一些更改,并且获得了相应的附加条件。非常感激。 – wildwally