Sql 显示同一表中行之间的差异

Sql 显示同一表中行之间的差异,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个名为Employee_audit的表,其模式如下: emp\u审计\u id 开斋节 名称 薪水 1. 1. 丹尼尔 1000 2. 1. 丹尼 1000 3. 1. 丹尼 3000 如果在CTE中为每一行指定一个行号,然后连接到下一行,则可以比较新旧值。联合两个不同的列名有点笨拙,但是,如果您需要更健壮的解决方案,您可能会考虑数据透视 显然,您还必须将所有值转换为通用数据类型,例如字符串 declare @Test table (emp_audit_id int, eid int, [

我有一个名为Employee_audit的表,其模式如下:

emp\u审计\u id 开斋节 名称 薪水 1. 1. 丹尼尔 1000 2. 1. 丹尼 1000 3. 1. 丹尼 3000
如果在CTE中为每一行指定一个行号,然后连接到下一行,则可以比较新旧值。联合两个不同的列名有点笨拙,但是,如果您需要更健壮的解决方案,您可能会考虑数据透视

显然,您还必须将所有值转换为通用数据类型,例如字符串

declare @Test table (emp_audit_id int, eid int, [name] varchar(32), salary money);

insert into @Test (emp_audit_id, eid, [name], salary)
values
(1, 1, 'Daniel', 1000),
(2, 1, 'Dani', 1000),
(3, 1, 'Danny', 3000);

with cte as (
    select emp_audit_id, eid, [name], salary
      , row_number() over (partition by eid order by emp_audit_id) rn
    from @Test
)
select C.emp_audit_id, 'name' columnName, P.[Name] oldValue, C.[name] newValue
from cte C
left join cte P on P.eid = C.eid and P.rn + 1 = C.rn
where coalesce(C.[name],'') != coalesce(P.[Name],'')
union all
select C.emp_audit_id, 'salary' columnName, convert(varchar(21),P.salary), convert(varchar(21),C.salary)
from cte C
left join cte P on P.eid = C.eid and P.rn + 1 = C.rn
where coalesce(C.salary,0) != coalesce(P.salary,0)
order by C.emp_audit_id, columnName;
返回:

emp\u审计\u id 列名 旧价值 新价值 1. 名称 无效的 丹尼尔 1. 薪水 无效的 1000 2. 名称 丹尼尔 丹尼 3. 名称 丹尼 丹尼 3. 薪水 1000 3000
超前和滞后功能将帮助您解决问题

diff计算需要查找diff的每列的差异

with diffs as (
    select 'name' colName, emp_audit_id, eid, lag(name, 1, null) over (partition by eid order by emp_audit_id) oldValue, name newValue
    from some_table
    union all
    select 'salary', emp_audit_id, eid, cast(lag(salary, 1, null) over (partition by eid order by emp_audit_id) as varchar), cast(salary as varchar) newValue
    from some_table
)
select * 
from diffs 
where oldValue <> newValue or oldValue is null 
order by emp_audit_id, eid

您已经标记了两个不同的数据库mysql和sql server。您确定需要这两种解决方案吗?请仅标记感兴趣的RDBMS。。。不是多重的。如果您将示例数据表示为DDL+DML,人们可以更容易地提供帮助。您想做什么?哪个数据库?行数不会给出集合中的上一个或下一个值,这就是超前或滞后的作用。所有这些函数都是添加到MySQL 8中的,所以您要么要求使用SQL Server,要么特别是MySQL 8SQL Server从2005年起就有更改跟踪功能,从2016年起就有时态表,基本上是所有受支持的版本。您可以创建一个比员工审计更好的解决方案。至于您想要的格式,无法确定哪一个更改引用了哪一行主键。@Techie321如果您想要SQL和T-SQL标记,它们才是真正的问题所在。SQL Server只是RDBMS,但T-SQL是您编写查询的工具。您好@PanagiotisKanavos这是一个有趣的观点-发布您的答案,让OP观点的最佳解决方案获胜吧!:这将是如此丑陋,即使它的工作。。。。要在每行中获得多个结果,可以使用行交叉应用。但是“选择”将需要每个属性字段有一个大小写,并需要一个大的大小写来确定字段名。@Techie321只有您自己才能找到它。针对具有真实数据的数据库运行这两种解决方案,并比较输出和特征IOs、CPU时间和执行时间。PanagiotisKanavos建议的解决方案可能是更好的方法。嘿@PanagiotisKanavos!我真的认为您需要将您的想法作为一个单独的答案发布如果您在SSMS中打开执行计划显示,它将显示运行每个查询所花费的时间百分比。因此,在我的窗口中,8%用于设置表和数据,58%用于运行我的查询,34%用于运行您的查询,我将它们都放在同一个窗口中。这是一个相当粗糙的、现成的、不太准确的统计数据,但它给出了两种解决方案中哪一种性能更好的想法。谢谢你,戴尔,它工作得非常好@Techie321不用担心-另一种解决方案也很好-让你知道,并且可以选择technnique。Dale,我们如何在一个选择查询中实现这一点,因为对于10个字段,10个选择查询和联合,所有这些都会使查询变慢。Techie321我知道你会问这个问题,这次你需要问一个新问题,确保它准确地反映了你的问题。@PanagiotisKanavos在评论中提出的建议将是一个起点。