SQL Server内部联接创建重复记录

时间:2016-04-27 22:09:22

标签: sql-server join

我有两张表,我之间创建了一个内部联接,并且由于一些奇怪的原因,它返回了我预期的更多记录。

表1中有6条记录,其中包括2个版本1' 2个记录版本2'以及2个记录版本3' 。表2中有10条记录,包括“版本1”和“版本1”的10条记录。如果我在版本字段之间进行内部联接,我会认为我只获得2条记录:表1和表2仅匹配版本1和#39;其中表1中只有2个。

但是,以下查询返回20条记录(如果它可以理解60条记录,如果它转换为交叉连接,这也是错误的):

SELECT * FROM TABLE2 T2 INNER JOIN TABLE1 T1 on T2.VersionKey = T1.VersionKey

任何人都可以帮助解释发生了什么吗?

我有另一组非常相似的表格给了我期望的结果,我不能在这里看到差异。

以下是基本的表格结构和数据。

CREATE TABLE [dbo].[Table1] (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [VersionKey] [int] NULL,
    CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([ID] ASC)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Table2] (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [VersionKey] [int] NULL,
    CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED ([ID] ASC) 
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

INSERT INTO [Table1] (VersionKey)
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 2 UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 3
GO

INSERT INTO [Table2] (VersionKey)
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION     
    SELECT 1
GO

2 个答案:

答案 0 :(得分:1)

您的设置脚本有错误。

INSERT INTO [Table2] (VersionKey)
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION      
    SELECT 1

最终UNION需要UNION ALL,否则您将删除重复项,只插入1行而不是10行。

SEDE上的固定脚本和查询结果在https://data.stackexchange.com/stackoverflow/query/478676/fixed-script

它返回20行,这是预期的和正确的。

逻辑上,左表中的每一行都与右表中的每一行进行比较。如果连接谓词的计算结果为true,则保留匹配。

如果内连接谓词总是正确的,例如On 1=1左边的每一行都会成功匹配右边的每一行,所以你最终会得到一个交叉连接。

在您的情况下,Table1中的VersionKey为1的两行在Table2中匹配10行,因此它们共同贡献了20行。 Table1中的其余行未成功连接到任何内容并贡献0行。

答案 1 :(得分:0)

上述信用归于马丁,但为了澄清其他人的答案......

正如上面其他人雄辩地解释的那样(再次感谢你的帮助)结果是正确的,并且使用我的例子,它应该产生20条记录。但是,这里解释了为什么会发生这是我原来的问题。

重复记录的原因是您要加入的表在您加入的字段中有重复记录。

enter image description here

这解决了为什么我在其他表中没有看到这一点的谜团,这些表分别包含2100和3个记录。表中没有重复的3条记录,因此在最终查询结果中没有重复。

为什么你通常可能看不到这是因为你可能通常会加入索引的主键字段,比如ID字段和我在这里所做的。在这些情况下,由于这些记录值始终可能是唯一的,因此您永远不会得到重复。

再次感谢大家的帮助。

这是我上面的更正代码,并修复了错误以重现结果。

CREATE TABLE [dbo].[Table1] (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [VersionKey] [int] NULL,
    CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([ID] ASC)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Table2] (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [VersionKey] [int] NULL,
    CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED ([ID] ASC) 
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

INSERT INTO [Table1] (VersionKey)
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 2 UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 3
GO

INSERT INTO [Table2] (VersionKey)
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL
    SELECT 1 UNION ALL   
    SELECT 1
GO

SELECT * FROM TABLE2 T2 INNER JOIN TABLE1 T1 on T2.VersionKey = T1.VersionKey