我正在使用大型SQL表,186列,257899行和计数。每次在主数据中更改某些内容时,它都会被添加。这是shadow
表的一部分,这些表允许我们查看不同字段发生的事件的审计历史记录。
我需要做的是查看谁更新,何时更新以及特定的更新顺序。我需要找到任何时候某个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
答案 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