查询以确定记录的累积更改

时间:2019-01-28 20:10:34

标签: sql sql-server tsql

鉴于下表包含示例行,我正在寻找一个查询,以提供对同一记录所做更改的汇总结果。所有更改都是针对另一个表(结果表)中的基本记录进行的,因此结果表的内容不是累积性的。

基本记录(从中进行所有更改)

enter image description here

突出显示已编辑的列

enter image description here

我正在寻找一个查询,该查询可以为我提供累积的更改(按日期顺序)。这将是结果行:

enter image description here

任何帮助表示赞赏!

更新---------------

让我澄清一下。被编辑的记录存在于一个表中,我们称其为[dbo]。[Base]。当某人从[dbo]。[Base]更新记录时,他的更新将进入[dbo]。[Updates]。因此,一个人总是从基表进行编辑。

在某个时刻,假设每天一次,我们需要使用以下规则来计算变化总和:

对于任何给定的记录,请确定每列的最新更改并进行最新更改。如果未对列进行任何更改,请从[dbo]。[Base]中获取值。因此,查看[dbo]。[Updates]表的一种方法是仅查看已更改的列。

enter image description here

请不要讨论这种方法的优点,我知道这很奇怪。我只需要弄清楚如何确定每个记录的最终状态。

谢谢!

2 个答案:

答案 0 :(得分:1)

这很脏,但是您可以试一下(在这里进行测试:https://rextester.com/MKSBU15593

我使用CTE对基本表和更新表进行初始CROSS JOIN的操作,然后执行第二步将其过滤到仅ID匹配的行。从那里开始,我为每一列使用FIRST_VALUE(),按ID值划分并按CASE表达式排序(如果Base列值与Update列值匹配,则为1,否则为0),以及Datemodified列以获取最新版本每列中的一个。

它吐出来

enter image description here

CREATE TABLE Base
(
    ID INT
    ,FNAME VARCHAR(100)
    ,LNAME VARCHAR(100)
    ,ADDRESS VARCHAR(100)
    ,RATING INT
    ,[TYPE] VARCHAR(5)
    ,SUBTYPE VARCHAR(5)
);

INSERT INTO dbo.Base
VALUES
(   100,'John','Doe','123 First',3,'Emp','W2'),
(   200,'Jane','Smith','Wacker Dr.',2,'Emp','W2');

CREATE TABLE Updates
(
    ID INT
    ,DATEMODIFIED DATE
    ,FNAME VARCHAR(100)
    ,LNAME VARCHAR(100)
    ,ADDRESS VARCHAR(100)
    ,RATING INT
    ,[TYPE] VARCHAR(5)
    ,SUBTYPE VARCHAR(5)
);

INSERT INTO dbo.Updates
VALUES
(   100,'1/15/2019','John','Doe','123 First St.',3,'Emp','W2'),
(   200,'1/15/2019','Jane','Smyth','Wacker Dr.',2,'Emp','W2'),
(   100,'1/17/2019','Johnny','Doe','123 First',3,'Emp','W2'),
(   200,'1/19/2019','Jane','Smith','2 Wacker Dr.',2,'Emp','W2'),
(   100,'1/20/2019','Jon','Doe','123 First',3,'Cont','W2');


WITH merged AS
(
    SELECT b.ID AS IDOrigin 
        ,'1/1/1900' AS DATEMODIFIEDOrigin
        ,b.FNAME AS FNAMEOrigin
        ,b.LNAME AS LNAMEOrigin
        ,b.ADDRESS AS ADDRESSOrigin
        ,b.RATING AS RATINGOrigin
        ,b.[TYPE]  AS TYPEOrigin
        ,b.SUBTYPE AS SUBTYPEOrigin
        ,u.*
    FROM base b
    CROSS JOIN
    dbo.Updates u
), filtered AS
(
    SELECT *
    FROM merged
    WHERE IDOrigin = ID
)

SELECT distinct
    ID
    ,FNAME = FIRST_VALUE(FNAME) OVER (PARTITION BY ID ORDER BY CASE WHEN FNAME = FNAMEOrigin THEN 1 ELSE 0 end, datemodified desc)
    ,LNAME = FIRST_VALUE(LNAME) OVER (PARTITION BY ID ORDER BY CASE WHEN LNAME = LNAMEOrigin THEN 1 ELSE 0 end, datemodified desc)
    ,ADDRESS = FIRST_VALUE(ADDRESS) OVER (PARTITION BY ID ORDER BY CASE WHEN ADDRESS = ADDRESSOrigin THEN 1 ELSE 0 end, datemodified desc)
    ,RATING = FIRST_VALUE(RATING) OVER (PARTITION BY ID ORDER BY CASE WHEN RATING = RATINGOrigin THEN 1 ELSE 0 end, datemodified desc)
    ,[TYPE] = FIRST_VALUE([TYPE]) OVER (PARTITION BY ID ORDER BY CASE WHEN [TYPE] = TYPEOrigin THEN 1 ELSE 0 end, datemodified desc)
    ,SUBTYPE = FIRST_VALUE(SUBTYPE) OVER (PARTITION BY ID ORDER BY CASE WHEN SUBTYPE = SUBTYPEOrigin THEN 1 ELSE 0 end, datemodified desc)
FROM filtered

答案 1 :(得分:0)

您不只想要最后一条记录吗?

select e.*
from edited e
where e.datemodified = (select max(e2.datemodified)
                        from edited e2
                        where e2.id = e.id
                       );