SQL Server-使用不同查询获取重复行

SQL Server-使用不同查询获取重复行,sql,sql-server,Sql,Sql Server,我正试图获得每个客户的子记录(地址)数量。我有两个问题,我想知道它们是否相同: SELECT a.AddressId, c.CustomerID, COUNT(*) AS NumDuplicates FROM Customers C INNER JOIN Addresses a ON c.AddressID = a.AddressID GROUP BY c.CustomerID, a.AddressId ORDER BY NumDupli

我正试图获得每个客户的子记录(地址)数量。我有两个问题,我想知道它们是否相同:

SELECT 
    a.AddressId,  c.CustomerID, COUNT(*) AS NumDuplicates 
FROM 
    Customers C
INNER JOIN 
    Addresses a ON c.AddressID = a.AddressID 
GROUP BY 
    c.CustomerID, a.AddressId 
ORDER BY 
    NumDuplicates DESC


SELECT 
    c.CustomerID,
    (SELECT COUNT(*) 
     FROM Addresses a 
     WHERE a.AddressID = c.AddressID) AS AddressCount
FROM 
    Customers c 
ORDER BY 
    AddressCount desc

如果不是,有什么区别?如果是,哪一个更有效?

这两个查询不同,因为第一个查询只返回地址表中至少有一个匹配项的客户。第二个返回所有客户,即使是那些不匹配且具有
AddressId
的客户也是空的

等效的第一个查询是:

SELECT c.CustomerID, COUNT(a.AddressId) AS NumDuplicates
FROM Customers C LEFT JOIN
     Addresses a
     ON c.AddressID = a.AddressID 
GROUP BY c.CustomerID
ORDER BY NumDuplicates DESC;

至于性能,你应该试一试。两种方法都有可能更快的原因。第二种方法不必进行聚合,但有一个相关的子查询。然而,SQLServer有一些加快连接和聚合的技巧。我猜相关子查询版本更快,但对于您的数据和服务器,我可能是错的。

将“*”放在计数或“a.AddressId”中有区别吗?是的。请注意,在Gordon的回答中,连接是左连接,而不是内部连接。如果在计数中使用*号,则对于没有地址的客户,它将返回1,但如果使用AddressId,它将返回0,因为计数忽略空值。@Eitan,是的<代码>计数(*)返回组中的行数
COUNT(a.AddressId)
返回
a.AddressId
不为
NULL
的行数。在这种特殊情况下,
a.AddressId
对于客户加入地址的行而言将是非空的。结果中表示没有地址的客户,因为使用了外部连接而不是内部连接。这是一个简单的测试。对于第一个问题,只需比较查询的结果。对于第二个,在ssms中运行它们,但首先单击“包含实际执行计划”按钮。这将在结果面板中为执行计划添加一个选项卡,使您能够轻松比较这两个查询的效率。