汇总后如何从审计 table 中分离出变更类型?
How can I split out change types from an audit table when they have been rolled up?
我正在尝试基于审计 table 构建查询,以便可以将对数据的更改归类为插入、修改或删除。
基本上我有一个请求 tables 存储每个请求的两个属性的旧值和新值:
请求ID
Value1Old
Value1New
Value2Old
Value2New
1
空
50
空
空
2
50
100
空
100
3
100
200
100
300
4
空
空
300
500
5
200
0
600
1000
6
空
空
1000
0
我正在寻找基于此生成的报告,拆分出每个请求的更改类别以及旧值和新值。从上面的 table 可以看出,对于每个请求,都可以有更改类别的组合,例如插入 Value1 和修改 Value2;或 Value1 和 Value2 的修改。
对于请求中的每个更改类别,都会有一个单独的行,即在上面的数据中,请求 2 和 5 有多个更改类别,因此被分开:
请求ID
改变
Value1Old
Value1New
Value2Old
Value2New
1
插入
空
50
空
空
2
插入
空
空
空
100
2
修改
50
100
空
空
3
修改
100
200
100
300
4
修改
空
空
300
500
5
修改
空
空
600
1000
5
删除
200
0
空
空
6
删除
空
空
1000
0
我已经能够通过冗长的查询获得我想要的结果,但是一定有更好的方法吗?它的可扩展性不是很好,最终我希望在大约 15 个值上执行此操作。
SELECT
*
FROM
(SELECT
RequestID,
UpdateTypes.[Name],
CASE
WHEN UpdateTypes.[Name] = 'Insert' THEN NULL
WHEN UpdateTypes.[Name] = 'Delete' AND Value1New = 0 THEN Value1Old
WHEN UpdateTypes.[Name] = 'Amend' AND Value1New <> 0 THEN Value1Old
ELSE NULL
END Value1Old,
CASE
WHEN UpdateTypes.[Name] = 'Insert' AND Value1Old IS NULL THEN Value1New
WHEN UpdateTypes.[Name] = 'Delete' AND Value1New = 0 THEN 0
WHEN UpdateTypes.[Name] = 'Amend' AND Value1Old <> 0 AND Value1New <> 0 THEN Value1New
ELSE NULL
END Value1New,
CASE
WHEN UpdateTypes.[Name] = 'Insert' THEN NULL
WHEN UpdateTypes.[Name] = 'Delete' AND Value2New = 0 THEN Value2Old
WHEN UpdateTypes.[Name] = 'Amend' AND Value2Old <> 0 AND Value2New <> 0 THEN Value2Old
ELSE NULL
END Value2Old,
CASE
WHEN UpdateTypes.[Name] = 'Insert' AND Value2Old IS NULL THEN Value2New
WHEN UpdateTypes.[Name] = 'Delete' AND Value2New = 0 THEN 0
WHEN UpdateTypes.[Name] = 'Amend' AND Value2Old <> 0 AND Value2New <> 0 THEN Value2New
ELSE NULL
END Value2New
FROM
Requests,
(SELECT 'Insert' [Name] UNION SELECT 'Amend' UNION SELECT 'Delete') AS UpdateTypes) Updates
WHERE
((Updates.[Name] = 'Insert')
AND ((Value1Old IS NULL AND Value1New IS NOT NULL)
OR (Value2Old IS NULL AND Value2New IS NOT NULL)))
OR ((Updates.[Name] = 'Delete')
AND ((Value1Old IS NOT NULL AND Value1New = 0)
OR (Value2Old IS NOT NULL AND Value2New = 0)))
OR ((Updates.[Name] = 'Amend')
AND ((Value1Old IS NOT NULL AND Value1New > 0)
OR (Value2Old IS NOT NULL AND Value2New > 0)))
ORDER BY
RequestID
这是一个 SQL Fiddle 数据,我当前的查询和预期结果:http://sqlfiddle.com/#!18/4ed0e/1/0
我建议一个可能的改进是将确定更改的逻辑移动到一个函数中:
create or alter function fnChange (@Old int, @New int)
returns varchar(10) as
begin
return (
select
case
when IsNull(@Old,0)=IsNull(@New,0) then null
else
case when @New=0 or @new is null then 'Delete' else
case when @Old is null then 'Insert'
else 'Amend' end
end
end
)
end
然后你可以重新使用它来简化。我相信以下内容会为您提供所需的输出:
with r as (
select RequestId, dbo.fnChange(Value1Old,Value1New) Change, Value1Old, Value1New, null Value2Old, null Value2New
from Requests
union all
select RequestId, dbo.fnChange(Value2Old,Value2New) Change, null Value1Old, null Value1New, Value2Old, Value2New
from Requests
)
select requestId, Change,
Max(Value1Old) Value1Old, Max(Value1New) value1New,
Max(Value2Old) Value2Old, Max(Value2New) value2New
from r where change is not null
group by requestId, Change
order by requestId, change desc
我正在尝试基于审计 table 构建查询,以便可以将对数据的更改归类为插入、修改或删除。
基本上我有一个请求 tables 存储每个请求的两个属性的旧值和新值:
请求ID | Value1Old | Value1New | Value2Old | Value2New |
---|---|---|---|---|
1 | 空 | 50 | 空 | 空 |
2 | 50 | 100 | 空 | 100 |
3 | 100 | 200 | 100 | 300 |
4 | 空 | 空 | 300 | 500 |
5 | 200 | 0 | 600 | 1000 |
6 | 空 | 空 | 1000 | 0 |
我正在寻找基于此生成的报告,拆分出每个请求的更改类别以及旧值和新值。从上面的 table 可以看出,对于每个请求,都可以有更改类别的组合,例如插入 Value1 和修改 Value2;或 Value1 和 Value2 的修改。
对于请求中的每个更改类别,都会有一个单独的行,即在上面的数据中,请求 2 和 5 有多个更改类别,因此被分开:
请求ID | 改变 | Value1Old | Value1New | Value2Old | Value2New |
---|---|---|---|---|---|
1 | 插入 | 空 | 50 | 空 | 空 |
2 | 插入 | 空 | 空 | 空 | 100 |
2 | 修改 | 50 | 100 | 空 | 空 |
3 | 修改 | 100 | 200 | 100 | 300 |
4 | 修改 | 空 | 空 | 300 | 500 |
5 | 修改 | 空 | 空 | 600 | 1000 |
5 | 删除 | 200 | 0 | 空 | 空 |
6 | 删除 | 空 | 空 | 1000 | 0 |
我已经能够通过冗长的查询获得我想要的结果,但是一定有更好的方法吗?它的可扩展性不是很好,最终我希望在大约 15 个值上执行此操作。
SELECT
*
FROM
(SELECT
RequestID,
UpdateTypes.[Name],
CASE
WHEN UpdateTypes.[Name] = 'Insert' THEN NULL
WHEN UpdateTypes.[Name] = 'Delete' AND Value1New = 0 THEN Value1Old
WHEN UpdateTypes.[Name] = 'Amend' AND Value1New <> 0 THEN Value1Old
ELSE NULL
END Value1Old,
CASE
WHEN UpdateTypes.[Name] = 'Insert' AND Value1Old IS NULL THEN Value1New
WHEN UpdateTypes.[Name] = 'Delete' AND Value1New = 0 THEN 0
WHEN UpdateTypes.[Name] = 'Amend' AND Value1Old <> 0 AND Value1New <> 0 THEN Value1New
ELSE NULL
END Value1New,
CASE
WHEN UpdateTypes.[Name] = 'Insert' THEN NULL
WHEN UpdateTypes.[Name] = 'Delete' AND Value2New = 0 THEN Value2Old
WHEN UpdateTypes.[Name] = 'Amend' AND Value2Old <> 0 AND Value2New <> 0 THEN Value2Old
ELSE NULL
END Value2Old,
CASE
WHEN UpdateTypes.[Name] = 'Insert' AND Value2Old IS NULL THEN Value2New
WHEN UpdateTypes.[Name] = 'Delete' AND Value2New = 0 THEN 0
WHEN UpdateTypes.[Name] = 'Amend' AND Value2Old <> 0 AND Value2New <> 0 THEN Value2New
ELSE NULL
END Value2New
FROM
Requests,
(SELECT 'Insert' [Name] UNION SELECT 'Amend' UNION SELECT 'Delete') AS UpdateTypes) Updates
WHERE
((Updates.[Name] = 'Insert')
AND ((Value1Old IS NULL AND Value1New IS NOT NULL)
OR (Value2Old IS NULL AND Value2New IS NOT NULL)))
OR ((Updates.[Name] = 'Delete')
AND ((Value1Old IS NOT NULL AND Value1New = 0)
OR (Value2Old IS NOT NULL AND Value2New = 0)))
OR ((Updates.[Name] = 'Amend')
AND ((Value1Old IS NOT NULL AND Value1New > 0)
OR (Value2Old IS NOT NULL AND Value2New > 0)))
ORDER BY
RequestID
这是一个 SQL Fiddle 数据,我当前的查询和预期结果:http://sqlfiddle.com/#!18/4ed0e/1/0
我建议一个可能的改进是将确定更改的逻辑移动到一个函数中:
create or alter function fnChange (@Old int, @New int)
returns varchar(10) as
begin
return (
select
case
when IsNull(@Old,0)=IsNull(@New,0) then null
else
case when @New=0 or @new is null then 'Delete' else
case when @Old is null then 'Insert'
else 'Amend' end
end
end
)
end
然后你可以重新使用它来简化。我相信以下内容会为您提供所需的输出:
with r as (
select RequestId, dbo.fnChange(Value1Old,Value1New) Change, Value1Old, Value1New, null Value2Old, null Value2New
from Requests
union all
select RequestId, dbo.fnChange(Value2Old,Value2New) Change, null Value1Old, null Value1New, Value2Old, Value2New
from Requests
)
select requestId, Change,
Max(Value1Old) Value1Old, Max(Value1New) value1New,
Max(Value2Old) Value2Old, Max(Value2New) value2New
from r where change is not null
group by requestId, Change
order by requestId, change desc