如何在SQL Server中的行之间交换数据?

时间:2017-07-13 02:26:52

标签: sql-server tsql

看起来很熟悉,但这是我想要在新旧数据之间交换值的新算法。我想获取最新数据然后将数据设置为NULL。我从PDF获取原始数据然后将其转换为Excel'xls'。

DECLARE @MyTable1 TABLE (Id int, 
                         Code int, 
                         RoomNo int, 
                         Class nvarchar(10), 
                         Price nvarchar(100), 
                         Size nvarchar(100)
                        )

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 
        1, 3, 10, 'C', '15,275,400 16,275,425', '(17,009) (17,010)'

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 2, 3, 9, 'C', '14,893,500 15,893,575', '(16,580) (16,585)'

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 3, 3, 8, 'C', '14,446,700 15,446,743', '(16,080) (16,088)'

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 4, 3, 7, 'C', null, null

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 5, null, null, null, '13,905,000', '(15,484)' -- this is the old data

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 6, null, null, null, '14.185.000', '(15,796)' -- I need the latest data

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 7, 3, 47, 'E', '20,833,600 21,833,600', '(18,630) (18,635)'

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 8, 3, 46, 'E', '20,807,600 21,807,600', '(18,610) (18,611)'

INSERT INTO @MyTable1(Id, Code, RoomNo, Class, Price, Size) 
    SELECT 9, 3, 45, 'E', '20,781,600 21,781,600', '(18,580) (18,588)'


SELECT * 
FROM @MyTable1

目前的结果:

Id          Code    RoomNo  Class   Price                       Size    
-------------------------------------------------------------------------
1           3       10      C       15,275,400 16,275,425       (17,009) (17,010)
2           3       9       C       14,893,500 15,893,575       (16,580) (16,585)
3           3       8       C       14,446,700 15,446,743       (16,080) (16,088)
4           3       7       C       NULL                        NULL
5           NULL    NULL    NULL    13,905,000                  (15,484)
6           NULL    NULL    NULL    14.185.000                  (15,796)
7           3       47      E       20,833,600 21,833,600       (18,630) (18,635)
8           3       46      E       20,807,600 21,807,600       (18,610) (18,611)
9           3       45      E       20,781,600 21,781,600       (18,580) (18,588)

我想实现:

Id          Code    RoomNo  Class   Price                       Size    
------------------------------------------------------------------------
1           3       10      C       15,275,400 16,275,425       (17,009) (17,010)
2           3       9       C       14,893,500 15,893,575       (16,580) (16,585)
3           3       8       C       14,446,700 15,446,743       (16,080) (16,088)
4           3       7       C       14.185.000                  (15,796)    -- get data from row 6 
5           NULL    NULL    NULL    NULL                        NULL
6           NULL    NULL    NULL    NULL                        NULL
7           3       47      E       20,833,600 21,833,600       (18,630) (18,635)
8           3       46      E       20,807,600 21,807,600       (18,610) (18,611)
9           3       45      E       20,781,600 21,781,600       (18,580) (18,588)

DECLARE @MyTable2 TABLE(Id int, Code int, RoomNo int, Class varchar(10), Price varchar(100), Size varchar(100))

INSERT INTO @MyTable2(Id, Code, RoomNo, Class, Price, Size) SELECT 1, 3, 7, 'G', '7,147,000', '148,346 (13,771)'
INSERT INTO @MyTable2(Id, Code, RoomNo, Class, Price, Size) SELECT 2, 3, 6, 'G', '7,111,000', '147,598 (13,701)'
INSERT INTO @MyTable2(Id, Code, RoomNo, Class, Price, Size) SELECT 3, 3, 5, 'G', null, '146,872'
INSERT INTO @MyTable2(Id, Code, RoomNo, Class, Price, Size) SELECT 4, null, null, null, '7,637,000', '158,516 (14,715)'


SELECT * FROM @MyTable2

目前的结果:

Id  Code    RoomNo  Class       Price           Size
1   3       7       G           7,147,000       148,346 (13,771)
2   3       6       G           7,111,000       147,598 (13,701)
3   3       5       G           NULL            146,872
4   NULL    NULL    NULL        7,637,000       158,516 (14,715)

我需要实现:

Id  Code    RoomNo  Class       Price           Size
1   3       7       G           7,147,000       148,346 (13,771)
2   3       6       G           7,111,000       147,598 (13,701)
3   3       5       G           7,637,000       158,516 (14,715)
4   NULL    NULL    NULL        NULL            NULL

1 个答案:

答案 0 :(得分:0)

让我们掷骰子,似乎我们可以把" 最新的"定义为在ID列上,其中较大的是最新的。请注意,与我们手中的打印数据不同,数据库不需要以某种默认顺序处理数据,因此除非有充分的理由(通常我们明确说明订单 ),它会选择订单,因为它的心情渴望。这是评论中的人们试图传达的内容,尽管他们可能会有不同的看法,尤其是你可能是数据库内容的新手。

接下来,数据有效性&更正,你想要识别不良记录,用相邻记录交叉检查,如果它看起来像一个记录被分成两半的情况,你想把它合并回原来的好处状态。

根据您的代码,数据样本以及我上面开发的理解,我认为此代码是您正在寻找的代码。它与您的代码兼容,我评论说明了什么是什么。 但请仔细检查IF EXISTS布尔区域下的好/坏逻辑,以及JOIN s 中ID序列的假设。

DECLARE @CurId int = (SELECT MAX(Id) FROM @MyTable1)
DECLARE @MinId int = (SELECT MIN(Id) FROM @MyTable1)

WHILE @CurId > @MinId -- For all except the first.
BEGIN
    -- Start boolean.
    IF EXISTS (
        SELECT 1
        FROM @MyTable1 AS Cur
        INNER JOIN @MyTable1 AS Prev ON Prev.Id = Cur.Id - 1 -- I'm assuming there are no gaps in IDs.
        WHERE Cur.Id = @CurId -- To limit checking to current ID.
          -- And for BIG, all left side is bad, all right side is good.
          AND (Cur.Code IS NULL AND Cur.RoomNo IS NULL AND Cur.Class IS NULL)
          AND (Cur.Price IS NOT NULL OR Cur.Size IS NOT NULL)
          -- And for SMALL, either same as BIG, or all left side is good, all right side is bad.
          AND 
          ( (   (Cur.Code IS NULL AND Cur.RoomNo IS NULL AND Cur.Class IS NULL)
                AND
                (Cur.Price IS NOT NULL OR Cur.Size IS NOT NULL)
            )
            OR
            (   (Prev.Code IS NOT NULL AND Prev.RoomNo IS NOT NULL AND Prev.Class IS NOT NULL)
                AND
                (Prev.Price IS NULL OR Prev.Size IS NULL)
    )     ) )
    -- End boolean.
    BEGIN
        -- Copy right side of this ID above once.
        UPDATE Prev
        SET Prev.Price = Cur.Price, Prev.Size = Cur.Size
        FROM @MyTable1 AS Prev
        INNER JOIN @MyTable1 AS Cur ON Cur.Id = Prev.Id + 1 -- I'm assuming there are no gaps in IDs.
        WHERE Cur.Id = @CurId
        -- NULL right side of this ID.
        UPDATE @MyTable1
        SET Price = NULL, Size = NULL
        WHERE Id = @CurId
    END

    SET @CurId -= 1 -- Gotta break them infinite loops.
END

SELECT * -- You shall not run this without my physical presence.
FROM @MyTable1