SQL左联接返回的记录比预期的多

SQL左联接返回的记录比预期的多,sql,sql-server,left-join,Sql,Sql Server,Left Join,当我只运行对dbo.contact的查询时,我尝试使用contactno列连接两个表dbo.contact和dbo.notes SELECT contactno, date_recd FROM dbo.contact WHERE (date_recd > CONVERT(DATETIME, '2016-01-01 00:00:00', 102)) AND (date_recd <= CONVERT(DATETIME

当我只运行对dbo.contact的查询时,我尝试使用contactno列连接两个表dbo.contact和dbo.notes

SELECT     
    contactno, date_recd
FROM         
    dbo.contact
WHERE     
    (date_recd > CONVERT(DATETIME, '2016-01-01 00:00:00', 102))
    AND (date_recd <= CONVERT(DATETIME, '2016-04-01 00:00:00', 102))

然后我得到22276张唱片。我不确定到底出了什么问题。我只想得到所有的11526怎么做?非常感谢您的帮助。

是的,执行左联接将返回第一个表中的所有行,并且只返回第二个表中匹配的行。但是,如果第二个表中有多行匹配,它将同时返回这两行,这可能会导致第一个表中的行重复

例如:

Table1
ID  Value
 1      A
 2      B
 3      C

Table2
ID  Value
 1      X
 1      Y
 2      Z

Select * from Table1 a
left join Table2 b
on a.ID = b.ID
返回:

ID  Value    ID  Value
 1      A     1     X
 1      A     1     Y
 2      B     2     Z
 3      C  Null  Null

它总共有四行,尽管示例中的表1只有三行。为了避免这种情况,您需要调整联接条件,使每行最多有一个匹配项,或者添加一些取消复制的步骤

如果每个联系人只需要一个备忘,可以使用外部应用:


通常,子查询将有一个ORDER BY,指定您想要的注释。但是,您的查询没有指定多个注释中的哪一个是首选注释。

上面的答案非常好,但我想发布解决我问题的代码。因此,我需要所有11526条记录,而不仅仅是每个联系人的前1条记录行。我需要所有的记录行,所以我最终将记录连接到一个字符串

Select  contact.contactno, 
STUFF(( Select '' + notes.noteline  FROM notes
 Where notes.contactno = contact.contactno 
order by notes.contactno for xml path (''),type).value('.','nvarchar(max)'),1,2,'') AS Notes 
From contact
WHERE 
(contact.date_recd > CONVERT(DATETIME, '2015-12-31 00:00:00', 102))
 AND
(contact.date_recd <= CONVERT(DATETIME, '2016-04-01 00:00:00', 102)) 
Group By contact.contactno;

每行可能有多个注释行contactno@vkp但是我要求它只给我contact表中的所有列,它不应该只返回11526条记录,如果它不存在,它应该为null,对吗?从查询中删除noteline并查看差异notes的主键是什么?在您的查询结果中也包括这一点。你应该看到一个联系人没有多个pk的注释
SELECT c.contactno, c.date_recd, n.noteline
FROM dbo.contact c OUTER APPLY
     (SELECT TOP 1 n.*
      FROM dbo.notes n 
      WHERE c.contactno = n.contactno
     ) n
WHERE (c.date_recd > CONVERT(DATETIME, '2016-01-01 00:00:00', 102)) AND
      (dc.date_recd <= CONVERT(DATETIME, '2016-04-01 00:00:00', 102));
Select  contact.contactno, 
STUFF(( Select '' + notes.noteline  FROM notes
 Where notes.contactno = contact.contactno 
order by notes.contactno for xml path (''),type).value('.','nvarchar(max)'),1,2,'') AS Notes 
From contact
WHERE 
(contact.date_recd > CONVERT(DATETIME, '2015-12-31 00:00:00', 102))
 AND
(contact.date_recd <= CONVERT(DATETIME, '2016-04-01 00:00:00', 102)) 
Group By contact.contactno;