2

我有这个查询:

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)

4

3 回答 3

3

如果ID两者VALUE都是,INT 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提供,ROW__NUMBER它比避免排序操作更有效的是

;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
于 2013-06-21T18:37:22.300 回答
1

这样做可能有一种更优雅的方式,但我认为我有一种方法。我找到第一行和最后一行并将结果连接在一起形成一行,然后进行数学运算。在只有 1 行的情况下,我不能 100% 确定你想要什么。我将其设为左外连接,以允许某些内容存在于 mins 而不是 maxs 中,然后作为连接条件的一部分,我排除了匹配的 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
;
于 2013-06-21T17:48:41.447 回答
-2

您的要求对我来说不是很清楚,但是您可以使用 EXCEPT 进行一组减法

于 2013-06-21T16:34:47.140 回答