从具有重复记录的两个表中检索公共行

时间:2014-11-29 06:40:13

标签: sql sql-server sql-server-2008 join sql-server-2008-r2

这是我的第一个问题,所以不知道哪里可能出错。 这是我的场景: 我有两个表:tblA和tblB。首先填充tblA中的某些数据然后填充tblB中的相同数据的过程。现在由于过程查询中的某些小故障,某些列的某些值未插入到tblB中,而是插入到tblA中。我现在想用tblA中的记录更新tblB。我找不到相应的更新记录。 为了简化任务,我已经准备好了使用查询的样本

--DROP TABLE #tblA
--DROP TABLE #tblB
--TRUNCATE TABLE #tblA
--TRUNCATE TABLE #tblB
CREATE TABLE #tblA (col1 char(2), col2 char(2), col3 int, col4 char)
CREATE TABLE #tblB (ID char(2),col1 char(2), col2 char(2), col3 int, col4 char)

INSERT INTO #tblA VALUES ('A','B',1,'C')
INSERT INTO #tblA VALUES ('A1','B',2,'C')
INSERT INTO #tblA VALUES ('A1','B',3,'C')

INSERT INTO #tblB VALUES ('I1','A','B',NULL,'C') -- Here we can see that values could not be inserted in col3
INSERT INTO #tblB VALUES ('I2','A1','B',NULL,'C')
INSERT INTO #tblB VALUES ('I3','A1','B',3,'C')

到目前为止我尝试了什么(不包括我尝试的其他查询,这给了我最接近的结果) (我甚至尝过了评论部分)

--UPDATE B
--SET B.col3=A.col3
SELECT  DISTINCT A.*, B.*
FROM #tblA A
INNER JOIN #tblB B
ON 1=1
AND A.col1=B.col1
AND A.col2 = B.col2
AND A.col4 = B.col4
--AND (A.col3<>B.col3)
AND (B.col3 IS NULL OR (B.col3 IS NOT NULL AND A.col3=B.col3))
--AND B.col3 IS NULL

我得到的结果如下:

col1    col2    col3    col4    ID  col1    col2    col3    col4
A        B       1       C      I1   A       B      NULL    C
A1       B       2       C      I2   A1      B      NULL    C
A1       B       3       C      I2   A1      B      NULL    C
A1       B       3       C      I3   A1      B      3       C

我应该在我的选择查询中进行哪些修改(这将是我的更新查询),以便我得到如下结果:(删除第三行的结果)

col1    col2    col3    col4    ID  col1    col2    col3    col4
A        B       1       C      I1   A       B      NULL    C
A1       B       2       C      I2   A1      B      NULL    C  
A1       B       3       C      I3   A1      B      3       C

2 个答案:

答案 0 :(得分:1)

不幸的是,根据您提供的信息,我认为没有一个很好的通用解决方案。我需要有关可能模式的更多信息。如上所述,明显的答案是:

SELECT *
FROM #tblA a
inner join #tblb b
on a.col1=b.col1
and a.col2 = b.col2
and a.col4 = b.col4
and a.col3 = right(b.ID,1)

或者,最后一行可以是and a.col3 = coalesce(b.col3,right(b.ID,1))

这取决于#tblb中的ID在Col3中的反映。我不认为这就是你想要的。从算法的角度来看,如果你不能依赖一个有意义的ID,我不确定是否有一个很好的方法来做到这一点。如果您可以描述要应用的一般算法,那么我们可以编写代码来匹配它。

例如,可能有意义的事情是:

  • Tbla在所有列上加入tblb
  • 当连接失败时,我想从tblb中选择第一条记录:
    • 匹配表a
    • 中的第1,2和4列
    • 在按ID
    • 排序时尚未加入tbla

在某些情况下,我可以看到该算法很有用。但实际上,您正在使用重复键连接表,这会使您在重复键的记录上进行交叉连接。

希望这会有所帮助。如果你更多地澄清你想要做的事情,我可能会帮助更多。

更新:

如果正如您在评论中所说,您只想确保两个表格完全匹配,那么您可以使用以下代码:

CREATE TABLE #tblA (col1 char(2), col2 char(2), col3 int, col4 char)
CREATE TABLE #tblB (col1 char(2), col2 char(2), col3 int, col4 char)

INSERT INTO #tblA VALUES ('A','B',1,'C')
INSERT INTO #tblA VALUES ('A1','B',2,'C')
INSERT INTO #tblA VALUES ('A1','B',3,'C')

INSERT INTO #tblB VALUES ('A','B',NULL,'C') 
INSERT INTO #tblB VALUES ('A1','B',NULL,'C')
INSERT INTO #tblB VALUES ('A1','B',3,'C')

delete from #tblb 
where NOT Exists (Select * from #tbla  a 
    where a.col1 = #tblb.col1
    and a.col2 = #tblb.col2
    and a.col3 = #tblb.col3
    and a.col4 = #tblb.col4)

INSERT #tblb
SELECT * from #tbla
where not exists (select * from #tblb b
    where b.col1 = #tbla.col1
    and b.col2 = #tbla.col2
    and b.col3 = #tbla.col3
    and b.col4 = #tbla.col4)

select * from #tbla a
inner join #tblb b
on b.col1 = a.col1
    and b.col2 = a.col2
    and b.col3 = a.col3
    and b.col4 = a.col4

当然,根据表的大小,行的大小,两个表的索引以及运行频率,简单地删除和重新插入可能更有意义。

只能更新不正确的列,但我认为编码和维护开销不值得,更不用说性能可能会非常差。

这有帮助吗?

答案 1 :(得分:0)

您不想使用内部联接,因为有多个值,您需要TOP 1或Top First记录的Col3值。

所以我更新了更新查询,如下所示,这会根据需要更新结果。

update  #tblB 
SET col3= 
( select top 1 a.col3 from #tblA a where A.col1=#tblB.col1
AND A.col2 = #tblB.col2
AND A.col4 = #tblB.col4)

select * from #tblB