如何过滤掉SQL中JOIN引起的重复记录?

时间:2016-12-21 21:48:45

标签: sql sql-server

我有一个简单的查询,它返回给定客户的电话号码列表。用户可以通过输入其地址的任何部分来搜索特定客户。客户可以拥有多个电话号码和地址。

以下是我的查询示例:

SELECT
ROW_NUMBER() OVER(PARTITION BY Customer.CustomerNumber, ORDER BY PhoneNumber.PhoneNumber) RowNumber,
Customer.CustomerNumber,
PhoneNumber.PhoneNumber
FROM Customer
JOIN PhoneNumber ON PhoneNumber.CustomerId = Customer.Id
JOIN CustomerAddress on CustomerAddress.CustomerId = Customer.Id

当我的客户有两个电话号码和两个地址时,以下是此查询产生的内容:

RowNumber     CustomerNumber     PhoneNumber
1             1                  111-111-1111
2             1                  222-222-2222
3             1                  111-111-1111
4             1                  222-222-2222

我期望的结果将是这样的:

RowNumber     CustomerNumber     PhoneNumber
1             1                  111-111-1111
2             1                  222-222-2222

当我删除地址表上的连接时,我只能产生上面所需的结果。

用户应该能够通过输入地址的任何部分来查找客户(例如:我想要显示任何在凤凰城有地址的用户)。虽然它没有显示在结果中,但它仍然应该是可过滤的。

我想我能做到这样的事情:

SELECT *, ROW_NUMBER() OVER(PARTITION BY Test.CustomerNumber ORDER BY Test.PhoneNumber) RowNumber
FROM
(
   SELECT
   DISTINCT 
   CustomerNumber, 
   PhoneNumber.PhoneNumber
   FROM Customer 
   JOIN PhoneNumber ON PhoneNumber.CustomerId = Customer.Id 
   JOIN CustomerAddress ON CustomerAddress.CustomerId = Customer.Id 
) Test

3 个答案:

答案 0 :(得分:2)

您没有从CustomerAddress表格中选择任何列,因此加入该表格只会为没有地址的客户抑制结果,并为具有多个地址的客户提供重复结果。

如果您不想要其中任何一种效果,请不要加入CustomerAddress。如果你只想要前者,那么你可以采用不同的方法,例如

SELECT
  ROW_NUMBER() OVER(PARTITION BY Customer.CustomerNumber,
    ORDER BY PhoneNumber.PhoneNumber) RowNumber,
  Customer.CustomerNumber,
  PhoneNumber.PhoneNumber
FROM
  Customer
  JOIN PhoneNumber ON PhoneNumber.CustomerId = Customer.Id
WHERE
  Customer.Id IN (SELECT CustomerId from CustomerAddress)

假设Customer.Id是主键,只有在PhoneNumber表中记录给定客户的重复电话号码时,才会产生重复。

答案 1 :(得分:2)

删除联接地址可能会影响用户按地址搜索的能力。如果这是问题,请将查询更改为使用exists

SELECT ROW_NUMBER() OVER (PARTITION BY c.CustomerNumber ORDER BY pn.PhoneNumber) as RowNumber,
       c.CustomerNumber,
       pn.PhoneNumber
FROM Customer c JOIN
     PhoneNumber pn
     ON pn.CustomerId = c.Id
WHERE EXISTS (SELECT 1
              FROM CustomerAddress ca
              WHERE ca.CustomerId = c.Id AND
                    ca.address like '%@ADDRESS%'  -- this is just an example of searching logic
             );

答案 2 :(得分:0)

将您的窗口功能更改为按子查询中的客户和电话号码进行分区。我一直用它来过滤欺骗。只需将分区设置为您的唯一键即可。

Select * from ( SELECT ROW_NUMBER() OVER(PARTITION BY Customer.CustomerNumber, PhoneNumber PhoneNumber, ORDER BY PhoneNumber.PhoneNumber) RowNumber, Customer.CustomerNumber, PhoneNumber.PhoneNumber FROM Customer JOIN PhoneNumber ON PhoneNumber.CustomerId = Customer.Id JOIN CustomerAddress on CustomerAddress.CustomerId = Customer.Id) Where RowNumber = 1