【问题标题】:Join two tables without unique records and compare two columns连接两个没有唯一记录的表并比较两列
【发布时间】:2013-08-04 13:33:02
【问题描述】:

我尝试加入两个没有唯一字段的表并根据日期进行比较。

考虑以下

表 A

System ID   Start   Process
132 1/17/2010   10/17/2010
132 2/21/2011   2/23/2011
132 1/16/2010   1/30/2010
132 1/16/2006   1/16/2006
132 1/16/2011   1/24/2010
132 1/30/2011   1/31/2011
132 1/30/2008   2/6/2008
132 2/5/2007    2/8/2007
132 2/5/2009    2/6/2009

表 B

System ID   T start T end
132 05/01/10    4/30/2011
132 05/01/11    4/30/2013

输出表

System ID   Start       Process     Check
132 1/17/2010       10/17/2010      Y
132 2/21/2011       2/23/2011       Y
132 1/16/2010       1/30/2010       Y
132 1/16/2006       1/16/2006       N
132 1/16/2011       1/24/2010       Y
132 1/30/2011       1/31/2011       Y
132 1/30/2008       2/6/2008        N
132 2/5/2007        2/8/2007        N
132 2/5/2009        2/6/2009        N

我正在尝试考虑表 A 中的所有记录,如果表 B 的“开始”出现在表 B“T Start”和“T End”,则输出表中的“Check”列将更新为“Y”。

我知道表只能基于唯一字段进行连接,所以我尝试在其中一个表中添加一个自动增量字段以避免重复,但问题是两个表都包含非唯一记录和每条记录都应考虑标识日期。每个表中的记录总数约为 60K。我有点震惊。感谢您的热心帮助。

【问题讨论】:

  • 您可以突出显示代码块和ctl-k 或单击{} 将它们大量缩进4 个空格以进行代码/表格格式化\
  • 联接不一定要出现在唯一的行上,但不清楚您在这里实际要完成什么。什么是A表,什么是B表,它们之间的关系是什么?在您的输出中,Check 是什么?你需要更清楚地知道你想在这里做什么。
  • 感谢您的更新。我会记下它。两个表之间的唯一关系是“系统 ID”,我正在尝试将表 A 的“开始”与表 B 的“T 开始”和“T 结束”进行比较,并更新输出表中的“检查”列。

标签: sql sql-server database


【解决方案1】:

您似乎正在尝试确定两个表中日期的重叠位置。以下应该这样做:

select a.*, (case when b.start is not null then 'Y' else 'N' end) as check
from TableA a left outer join
     TableB b
     on a.start <= b.Tend and
        a.end >= b.Tstart and
        (a.start <> b.Tstart and a.end <> b.Tend) and
        a.SystemId = b.SystemId;

可以使用任何类型的关系连接表。当您说“唯一字段”时,您可能指的是“等值连接”。这是连接条件由各个字段之间的“等于”组成的情况。等值连接的优点是处理效率更高(在大多数情况下)。

【讨论】:

  • 谢谢戈登。对此,我真的非常感激。我将开始探索它。
  • 嗨,Gordan,我尝试了这两个建议;我通过在您的逻辑中添加自动增量字段来避免重复进行了更改。结果是全部为 Y 或全部为 N。我不确定发生了什么。我尝试复制数据集并尝试相同的方法,它适用于我的重复数据集,但不适用于我的实际数据集。我不确定为什么它不起作用?我验证了数据集,似乎没问题。有什么建议可以验证我的数据集吗?系统 ID 为 varchar,其余字段为日期时间。
  • @sasecse 。 . .我不确定加入是否还需要系统 ID。在问题中,只有一个系统 id,但如果有多个值,那么所有记录可能都会匹配。另外,一条记录匹配自己(由于&lt;=&gt;=),我刚刚修复了。
  • 嗨,戈登,感谢您的更新。我不确定为什么这个逻辑适用于我的数据集。我再次尝试使用手动示例。
【解决方案2】:

当您检查重叠时,连接表格时必须小心,例如,如果您在表格 B 中有 2 个日期范围与表格 A 中的给定范围重叠,则表格 A 中的行将出现在结果中两次.因此,我建议使用exists 来检查重叠:

select
    A.*,
    case
        when exists
        (
             select *
             from TableB as B
             where B.[System ID] = A.[System ID] and B.[T end] >= A.[Start] and B.[T start] <= A.[Process]
        )
        then 'Y'
        else 'N'
    end as [Checked]
from TableA as A

或使用apply

select
    A.*, case when B.[System ID] is not null then 'Y' else 'N' end as [Checked]
from TableA as A
    outer apply (
        select top 1 *
        from TableB as B
        where B.[System ID] = A.[System ID] and B.[T end] >= A.[Start] and B.[T start] <= A.[Process]
    ) as B

查看sqlfiddle 示例与您的数据。

【讨论】:

  • 感谢您的注意。我真的很感激。
  • 嗨 Roman,我通过在我的实际数据集中再添加一个条件(使用系统 ID)来尝试上述逻辑,但结果是全部为 Y 或全部为 N。我不确定发生了什么。我尝试复制数据集并尝试相同的逻辑,它适用于我的重复数据集,但它不适用于我的实际数据集。我不确定为什么它不起作用?有什么建议吗?
  • 您好 Roman,感谢您的快速回复。我尝试使用 Gordon 建议的 Exists 和 Join。现在我尝试使用 Outer apply,我得到的都是 N。
  • 您能否粘贴 A 中的几行和 B 中的所有行,以便我进行测试?
  • 我认为我没有足够的权限来复制它。 System Id 是 varchar,Start 和 End 是日期时间字段。我真的很抱歉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 2019-10-08
  • 2014-12-26
  • 2019-06-24
  • 1970-01-01
相关资源
最近更新 更多