如何在内连接子句中区分重复行(按字段)

时间:2014-01-13 10:24:31

标签: sql db2

我有两张桌子:

Customers -> CustomerId, Name 

Phones -> PhoneId , CustomerId , Phone

此表通过CustomerId字段加入。每个客户都有多个电话 在电话表中。我只需要其中一个。我怎样才能做到这一点。

SELECT 
       Customers.CustomerId , 
       Customers.Name ,
       Phones.Phone
FROM Customers 
     INNER JOIN Phones ON Customers.CustomerId = Phones.CustomerId 

在这种情况下我会得到类似的东西:

+----------+----+-----------+
|CustomerId|Name|Phone      |
+----------+----+-----------+
|1010      |Jack|999-999-999|
+----------+----+-----------+
|1010      |Jack|888-888-888|
+----------+----+-----------+
|1010      |Jack|111-111-111|
+----------+----+-----------+
|2020      |Pit |123-123-123|
+----------+----+-----------+
|2020      |Pit |321-321-321|
+----------+----+-----------+

但我只需要一个客户和一个电话号码,如:

+----------+----+-----------+
|CustomerId|Name|Phone      |
+----------+----+-----------+
|1010      |Jack|888-888-888|
+----------+----+-----------+
|2020      |Pit |123-123-123|
+----------+----+-----------+

我尝试使用子查询来做到这一点:

   SELECT 
   c.CustomerId , 
   c.Name ,
   SELECT ( p.Phone FROM Phones WHERE p.CustomeId=c.CustomerId FETCH FIRST 1 ROWS ONLY)
   FROM Customers c

但是它非常适合SLLOOOW,这就是为什么我不能使用子查询。我怎么能这样做呢?

4 个答案:

答案 0 :(得分:1)

Row_Number()功能会帮助你。

WITH X AS
(SELECT C.CustomerId
      , C.Name
      , P.Phone
      , ROW_NUMBER() OVER (PARTITION BY P.CustomerID) AS Pick
  FROM Customers C
  JOIN Phones    P   ON C.CustomerId = P.CustomerId 
)
SELECT CustomerID
     , Name
     , Phone
  FROM X
  WHERE Pick = 1

这将为与给定客户有关的每个电话号码分配一个基数,并仅选择第一个。现在在这种情况下,我们随意挑选哪个电话号码是第一个。

假设您的电话表中有其他字段可能有助于您确定哪个字段最佳选择。假设您有一个Last_Used时间戳,并且最佳选择的数字可以是最近使用的数字。然后你可以使用这样的表达式:

ROW_NUMBER() OVER (PARTITION BY P.CustomerID  ORDER BY P.Last_Used desc)  

当然,如果你在讨论其他类型的字段,那么简单地使用MIN()或MAX()和GROUP BY CustomerID可能是有意义的。但我看不出任何理由这样做的电话号码。

答案 1 :(得分:0)

最好的选择是使用pivot。有关更多信息,请访问此处http://blog.sqlauthority.com/2008/06/07/sql-server-pivot-and-unpivot-table-examples/。通过使用它,您也可以查看所有电话号码....

答案 2 :(得分:0)

这将为每个客户ID返回一个电话号码

SELECT 
    c.CustomerId, 
    c.Name,
    Min(p.Phone) Phone -- Or Max(p.Phone)
FROM Customers c
    LET OUTER JOIN Phones p on c.CustomeId = p.CustomeId
GROUP BY c.CustomerId, c.Name

答案 3 :(得分:0)

试试这个

Note: This is not tested code

SELECT 
       distinct Phones.Phone,
       Customers.CustomerId , 
       Customers.Name 

FROM Customers 
     INNER JOIN Phones ON Customers.CustomerId = Phones.CustomerId