如何查找状态更新以及创建状态的人员

时间:2017-07-20 19:03:05

标签: sql-server set-based

我正在使用大型SQL表,186列,257899行和计数。每次在主数据中更改某些内容时,它都会被添加。这是shadow表的一部分,这些表允许我们查看不同字段发生的事件的审计历史记录。

我需要做的是查看谁更新,何时更新以及特定的更新顺序。我需要找到任何时候某个3个用户更新主表来从

  • 比尔=>活性
  • 比尔=>没有比尔
  • 有效=>正在进行中

我需要收集的是

  1. 正在切换状态以及切换到的状态(来自列表 以上)
  2. 下面的3个用户列表中进行更新的用户名
  3. 更新日期时间
  4. ClaimNumber
  5. 我正在寻找的用户我无法提供他们的名字,所以我们会选择:

    • 用户1
    • 用户2
    • 用户3

    我最近学会了在SQL中以基于集合的方式处理事务,但我并不完全可以理解这一点。我知道我可以在表中循环并找到各个用户的任何更新,然后循环查看这些更新以查找是否有任何符合上述标准的内容,但我知道与基于批准的集合相比,这将是缓慢的。

    我刚刚开始研究这个问题,所以我还没有任何代码,但是当我尝试不同的东西时,我会更新这个问题。

    我只是不知道如何弄清楚如何使它成为基于集合的问题?

    更新

    以下是一些示例数据:

    创建#TestingData作为数据表,#TestingTable作为影子表,然后填充样本数据。

    create table #TestingTable(Id int,SMState varchar(50),UpdatedBy varchar(50),UpdatedOn datetime,cd_ClaimNumber varchar(50))
    
    create table #TestingData(Id int,SMState varchar(50),UpdatedBy varchar(50),UpdatedOn datetime,cd_ClaimNumber varchar(50))
    
    insert into #TestingData([Id],[UpdatedBy],[UpdatedOn],[cd_ClaimNumber],SMState)
    Values  (1,'John Doe','2015-10-25 12:00:00',208692,'Bill'),
            (2,'John Doe','2015-10-25 12:00:00',297983,'Bill'),
            (3,'John Doe','2015-10-25 13:00:00',697920,'Bill'),        
            (4,'John Doe','2015-10-25 12:00:00',992196,'Bill')
    
    INSERT INTO #TestingTable([Id],[UpdatedBy],[UpdatedOn],[cd_ClaimNumber],SMState) 
    VALUES
          (1,'John Jones','2015-10-24 13:00:00',208692,'No Bill'),
          (2,'John Jones','2015-10-24 12:00:00',208692,'Bill'),
          (3,'John Jones','2015-10-23 12:00:00',208692,'In Progress'),
          (4,'John Jones','2015-10-22 16:00:00',208692,'Active'),
          (5,'John Jones','2015-10-22 14:00:00',208692,'No Bill'),
          (6,'John Jones','2015-10-22 12:00:00',208692,'Bill'),
          (7,'John Jones','2015-10-24 12:00:00',297983,'Bill'),
          (8,'John Jones','2015-10-23 14:00:00',297983,'Active'),
          (9,'John Jones','2015-10-23 13:00:00',297983,'In Progress'),
          (10,'John Jones','2015-10-23 12:00:00',297983,'Active'),
          (11,'John Jones','2015-10-22 12:00:00',297983,'Bill'),
          (12,'Jeffery Sampson','2015-10-24 13:00:00',697920,'No Bill'),
          (13,'Jeffery Sampson','2015-10-24 12:00:00',697920,'Bill'),
          (14,'Jeffery Sampson','2015-10-23 12:00:00',697920,'In Progress'),
          (15,'Jeffery Sampson','2015-10-22 16:00:00',697920,'Active'),
          (16,'Jeffery Sampson','2015-10-22 14:00:00',697920,'No Bill'),
          (17,'Jeffery Sampson','2015-10-22 12:00:00',697920,'Bill'),
          (18,'Jeffery Sampson','2015-10-24 12:00:00',992196,'Bill'),
          (19,'Jeffery Sampson','2015-10-23 14:00:00',992196,'Active'),
          (20,'Jeffery Sampson','2015-10-23 13:00:00',992196,'In Progress'),
          (21,'Jeffery Sampson','2015-10-23 12:00:00',992196,'Active'),
          (22,'Jeffery Sampson','2015-10-22 12:00:00',992196,'Bill')
    

    以下是影子表与上述数据的对比:

    +----+-------------+-----------------+---------------------+----------------+
    | Id |   SMState   |    UpdatedBy    |      UpdatedOn      | cd_ClaimNumber |
    +----+-------------+-----------------+---------------------+----------------+
    |  1 | No Bill     | John Jones      | 24.10.2015 13:00:00 |         208692 |
    |  2 | Bill        | John Jones      | 24.10.2015 12:00:00 |         208692 |
    |  3 | In Progress | John Jones      | 23.10.2015 12:00:00 |         208692 |
    |  4 | Active      | John Jones      | 22.10.2015 16:00:00 |         208692 |
    |  5 | No Bill     | John Jones      | 22.10.2015 14:00:00 |         208692 |
    |  6 | Bill        | John Jones      | 22.10.2015 12:00:00 |         208692 |
    |  7 | Bill        | John Jones      | 24.10.2015 12:00:00 |         297983 |
    |  8 | Active      | John Jones      | 23.10.2015 14:00:00 |         297983 |
    |  9 | In Progress | John Jones      | 23.10.2015 13:00:00 |         297983 |
    | 10 | Active      | John Jones      | 23.10.2015 12:00:00 |         297983 |
    | 11 | Bill        | John Jones      | 22.10.2015 12:00:00 |         297983 |
    | 12 | No Bill     | Jeffery Sampson | 24.10.2015 13:00:00 |         697920 |
    | 13 | Bill        | Jeffery Sampson | 24.10.2015 12:00:00 |         697920 |
    | 14 | In Progress | Jeffery Sampson | 23.10.2015 12:00:00 |         697920 |
    | 15 | Active      | Jeffery Sampson | 22.10.2015 16:00:00 |         697920 |
    | 16 | No Bill     | Jeffery Sampson | 22.10.2015 14:00:00 |         697920 |
    | 17 | Bill        | Jeffery Sampson | 22.10.2015 12:00:00 |         697920 |
    | 18 | Bill        | Jeffery Sampson | 24.10.2015 12:00:00 |         992196 |
    | 19 | Active      | Jeffery Sampson | 23.10.2015 14:00:00 |         992196 |
    | 20 | In Progress | Jeffery Sampson | 23.10.2015 13:00:00 |         992196 |
    | 21 | Active      | Jeffery Sampson | 23.10.2015 12:00:00 |         992196 |
    | 22 | Bill        | Jeffery Sampson | 22.10.2015 12:00:00 |         992196 |
    +----+-------------+-----------------+---------------------+----------------+
    

    以下是数据表与上述数据的对比:

    +----+---------+-----------+---------------------+----------------+
    | Id | SMState | UpdatedBy |      UpdatedOn      | cd_ClaimNumber |
    +----+---------+-----------+---------------------+----------------+
    |  1 | Bill    | John Doe  | 25.10.2015 12:00:00 |         208692 |
    |  2 | Bill    | John Doe  | 25.10.2015 12:00:00 |         297983 |
    |  3 | Bill    | John Doe  | 25.10.2015 13:00:00 |         697920 |
    |  4 | Bill    | John Doe  | 25.10.2015 12:00:00 |         992196 |
    +----+---------+-----------+---------------------+----------------+
    

    我正在寻找的最终结果是这样的:

    +---------------+-----------+-----------------+---------------------+-------------+
    | CurrentStatus | OldStatus |    UpdatedBy    |      UpdateOn       | ClaimNumber |
    +---------------+-----------+-----------------+---------------------+-------------+
    | No Bill       | Bill      | John Jones      | 22.10.2015 14:00:00 |      208692 |
    | In Progress   | Active    | John Jones      | 23.10.2015 12:00:00 |      208692 |
    | No Bill       | Bill      | John Jones      | 24.10.2015 13:00:00 |      208692 |
    | Active        | Bill      | John Jones      | 23.10.2015 12:00:00 |      297983 |
    | In Progress   | Active    | John Jones      | 23.10.2015 13:00:00 |      297983 |
    | No Bill       | Bill      | Jeffery Sampson | 22.10.2015 14:00:00 |      697920 |
    | In Progress   | Active    | Jeffery Sampson | 23.10.2015 12:00:00 |      697920 |
    | No Bill       | Bill      | Jeffery Sampson | 24.10.2015 13:00:00 |      697920 |
    | Active        | Bill      | Jeffery Sampson | 23.10.2015 12:00:00 |      992196 |
    | In Progress   | Active    | Jeffery Sampson | 23.10.2015 13:00:00 |      992196 |
    +---------------+-----------+-----------------+---------------------+-------------+
    

    这是我尝试过的:

    with Test_1 as
    ( select ROW_NUMBER() over(order by pdr.cd_ClaimNumber,pdr.UpdatedOn) as RowID,* from #TestingTable pdr)
    select t1.cd_ClaimNumber,t1.UpdatedOn, t1.SMState OldStatus, t2.SMState NewStatus, t1.UpdatedBy
    from Test_1 t1
    join Test_1 t2 on t2.RowID = t1.RowID + 1
    where t1.cd_ClaimNumber = t2.cd_ClaimNumber
        and t1.SMState != t2.SMState
    order by t1.cd_ClaimNumber,t2.UpdatedOn
    

    这给了我这个结果:

    +----------------+---------------------+-------------+-------------+-----------------+
    | cd_ClaimNumber |      UpdatedOn      |  OldStatus  |  NewStatus  |    UpdatedBy    |
    +----------------+---------------------+-------------+-------------+-----------------+
    |         208692 | 22.10.2015 12:00:00 | Bill        | No Bill     | John Jones      |
    |         208692 | 22.10.2015 14:00:00 | No Bill     | Active      | John Jones      |
    |         208692 | 22.10.2015 16:00:00 | Active      | In Progress | John Jones      |
    |         208692 | 23.10.2015 12:00:00 | In Progress | Bill        | John Jones      |
    |         208692 | 24.10.2015 12:00:00 | Bill        | No Bill     | John Jones      |
    |         297983 | 22.10.2015 12:00:00 | Bill        | Active      | John Jones      |
    |         297983 | 23.10.2015 12:00:00 | Active      | In Progress | John Jones      |
    |         297983 | 23.10.2015 13:00:00 | In Progress | Active      | John Jones      |
    |         297983 | 23.10.2015 14:00:00 | Active      | Bill        | John Jones      |
    |         697920 | 22.10.2015 12:00:00 | Bill        | No Bill     | Jeffery Sampson |
    |         697920 | 22.10.2015 14:00:00 | No Bill     | Active      | Jeffery Sampson |
    |         697920 | 22.10.2015 16:00:00 | Active      | In Progress | Jeffery Sampson |
    |         697920 | 23.10.2015 12:00:00 | In Progress | Bill        | Jeffery Sampson |
    |         697920 | 24.10.2015 12:00:00 | Bill        | No Bill     | Jeffery Sampson |
    |         992196 | 22.10.2015 12:00:00 | Bill        | Active      | Jeffery Sampson |
    |         992196 | 23.10.2015 12:00:00 | Active      | In Progress | Jeffery Sampson |
    |         992196 | 23.10.2015 13:00:00 | In Progress | Active      | Jeffery Sampson |
    |         992196 | 23.10.2015 14:00:00 | Active      | Bill        | Jeffery Sampson |
    +----------------+---------------------+-------------+-------------+-----------------+
    

    这不太奏效。它得到了所有的变化,而不仅仅是我正在寻找的变化。我的基础是Programming SQL in a Set-Based Way

1 个答案:

答案 0 :(得分:0)

如果您的审计表中有适当的列,那么我将其视为prety直接查询。当然我希望这里不包括claimnumber,但是会有一些原始数据的引用然后它将是简单的join。但根据您的审计表结构,可能还有更多内容。

SELECT old, new, who, when, claimnumber

FROM table

WHERE (    (old = 'Bill' AND new = 'Active') 
        OR (old = 'Bill' AND new = 'No Bill')
        OR (old = 'Active' AND new = 'In Progress')) 
      AND user IN ('User1','User2','User3')

 ORDER BY when

另一个故事是拥有支持此查询的索引。

如果您的审计表只包含一个包含主记录状态的字段,那么这可能是另一个版本。

create table audit ([status] nvarchar(20), [user] nvarchar(20), [date] date, [claimnumber] int)
insert into audit values 
('Bill', 'User5', '2017-05-01', 001),
('Bill', 'User4', '2017-05-03', 005),
('Active', 'User2', '2017-05-05', 001),
('No Bill', 'User3', '2017-05-10', 005),
('In Progress', 'User1', '2017-05-08', 001)


SELECT * FROM (
SELECT LAG([status]) OVER (PARTITION BY [claimnumber] ORDER BY [claimnumber], [date]) as oldstatus, *
FROM audit
) AS A
WHERE [user] IN ('User1','User2','User3') AND 
      (([oldstatus]='Bill' AND [status] = 'Active')
       OR ([oldstatus]='Bill' AND [status] = 'No Bill')
       OR ([oldstatus]='Active' AND [status] = 'In Progress'))
ORDER BY [claimnumber], [date] 

结果

oldstatus   status      user    date                 claimnumber
Bill        Active      User2   05.05.2017 00:00:00  1
Active      In Progress User1   08.05.2017 00:00:00  1
Bill        No Bill     User3   10.05.2017 00:00:00  5