【问题标题】:SQL Server Compare similar tables with querySQL Server 用查询比较相似表
【发布时间】:2011-04-11 18:01:28
【问题描述】:

简单的概念,我们基本上是在做一些审计,比较进来的东西,以及处理过程中实际发生的事情。我正在寻找一种更好的方法来执行查询,该查询可以与名称和潜在类型略有不同的列进行并排表比较。

数据库布局:

表(*为连接条件)

日志(未更改的数据记录。)
- 日志ID
- 记录 ID*
- 名称
- 日期
- 地址
- 产品
- 等等

审核(后处理记录)
- CardID*
- 车名
- 部署日期
- 送货地址
- 选项
- 等等

例如,如果您忽略了烦人的编写复杂性和性能问题,这工作。

查询只是连接左右并选择它们作为字符串。显示匹配的每个字段。

select 
  cast(log.RecordID as varchar(40)) + '=' + cast(audit.CardID as varchar(40),
  log.Name+ '=' + audit.Name ,
  cast(log.Date as varchar(40)) + '=' + cast(audit.DeploymentDate as varchar(40), 
  log.Address + '=' + audit.ShippingAddress,
  log.Products+ '=' + audit.Options
  --etc
from Audit audit, Log log
  where audit.CardID=log.RecordId

会输出如下内容:

1=1 Test=TestName 11/09/2009=11/10/2009 null=我的地址 null=Wheels

这可行,但构建起来非常烦人。我想到的另一件事是给列取别名,合并两个表,然后对它们进行排序,使它们成为列表形式。这将允许我查看列比较。这带来了 union all 的明显开销。

即:

日志 1 测试 11/09/2009 null,null
审计 1 TestName 11/10/2009 我的地址轮子

对审计这些数据的更好方法有什么建议吗?

让我知道您可能还有什么其他问题。

附加说明。我们将要减少不重要的信息,因此在某些情况下,如果它们相等,我们可能会将列清空(但我知道它太慢了)

  case when log.[Name]<>audit.[CarName] then (log.[Name] + '!=' + audit.[CarName]) else null end

或者如果我们采用第二种方式

  nullif(log.[Name], audit.[CarName]) as [Name]
  ,nullif(audit.[CarName], log.[Name]) as [Name]

【问题讨论】:

  • 更好的方法是什么意思?您是否正在寻找一种更好的方式来显示数据,以便您可以更清楚地阅读它?是否要将数据限制为仅具有差异的数据?
  • 在性能和可读性方面更好。我们正在做大量工作来分析这些数据,因此我们将根据需要进行过滤,但我们也可能会做类似上述的事情。如果某些列相等,我们可能会将它们清空,以便我们可以更快地筛选结果集。
  • 你想达到什么目的?请提供更多信息。
  • 给我一些指导你的问题?我已经说了很多,我担心如果我添加更多它只会混淆。让我知道什么是令人困惑的,我会回去重新措辞。
  • 您是否研究过第三方比较工具,例如 Redgate SQL Data Compare?

标签: sql sql-server sql-server-2008 analysis


【解决方案1】:

我发现 Jeff Smith 给出的 here 例程有助于过去进行表格比较。这至少可以为您提供一个良好的起点。该链接上给出的代码是:

CREATE PROCEDURE CompareTables(@table1 varchar(100), 
    @table2 Varchar(100), @T1ColumnList varchar(1000),
    @T2ColumnList varchar(1000) = '')
AS

-- Table1, Table2 are the tables or views to compare.
-- T1ColumnList is the list of columns to compare, from table1.
-- Just list them comma-separated, like in a GROUP BY clause.
-- If T2ColumnList is not specified, it is assumed to be the same
-- as T1ColumnList.  Otherwise, list the columns of Table2 in
-- the same order as the columns in table1 that you wish to compare.
--
-- The result is all records from either table that do NOT match
-- the other table, along with which table the record is from.

declare @SQL varchar(8000);

IF @t2ColumnList = '' SET @T2ColumnList = @T1ColumnList

set @SQL = 'SELECT ''' + @table1 + ''' AS TableName, ' + @t1ColumnList +
 ' FROM ' + @Table1 + ' UNION ALL SELECT ''' + @table2 + ''' As TableName, ' +
 @t2ColumnList + ' FROM ' + @Table2

set @SQL = 'SELECT Max(TableName) as TableName, ' + @t1ColumnList +
 ' FROM (' + @SQL + ') A GROUP BY ' + @t1ColumnList + 
 ' HAVING COUNT(*) = 1'

exec ( @SQL)

【讨论】:

    【解决方案2】:

    这样的东西对你有用吗:

    select 
      (Case when log.RecordID = audit.CardID THEN 1 else 0) as RecordIdEqual,
      (Case when log.Name = audit.Name THEN 1 else 0) as NamesEqual ,
      (Case when log.Date = audit.DeploymentDate THEN 1 else 0) as DatesEqual, 
      (Case when log.Address = audit.ShippingAddress THEN 1 else 0) as AddressEqual,
      (Case when log.Products = audit.Options THEN 1 else 0) as ProductsEqual
      --etc
    from Audit audit, Log log
      where audit.CardID=log.RecordId
    

    这将根据列名称为您提供相等的细分。似乎它可能比进行所有转换并必须解释结果字符串更容易......

    【讨论】:

    • 我进行强制转换是因为如果记录相等,我们可能需要知道列的值。假设 A 列是正确的(并且是唯一标识符)并且 B 是不正确的,我们需要查看 A 的值。但我可能会使用这种策略来过滤掉不那么重要的值。
    猜你喜欢
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多