当连接在多个元素上时的Where子句

时间:2015-09-24 20:13:18

标签: sql sql-server

客户

number = 666,ContactId = 1a1b ..

联系

Id = 1a1b ..,Name = Bob smith

地址

地址= 350 king road,AddressType = officle,Order = 1,ContactId = 1a1b 地址= 123皇后街,AddressType = home,Order = 2,ContactId = 1a1b

SQL查询:

SELECT TOP (100)  
    dbo.Customer.Number, dbo.Contact.Name, 
    dbo.Address.StreetAddress, dbo.Address.Order 
FROM
    dbo.Customer 
LEFT JOIN
    dbo.Contact ON dbo.Customer.ContactId = dbo.Contact.Id 
LEFT JOIN
    dbo.Address ON dbo.Contact.Id = dbo.Address.ContactId
WHERE
    Contact.Name LIKE '%o%' OR Address.StreetAddress LIKE '%o%'

返回以下结果:

666 | Bob Smith | 350 king road | 1
666 | Bob Smith | 123 queen street | 2

问题

我想获得第一个可用地址(350王道/序列1)而不是两者(即使搜索字符串与两个地址匹配)

当匹配仅在第二个地址上时(比如在我的示例中执行类似%q%而不是类似%o%)我想返回此特定地址而不是其他地址

是否可以在SQL中执行此操作?顺便说一句,我的目标也是尽可能快地得到结果,还有其他方法可以在“一对多”连接表中进行这种搜索吗?

我只需要一些东西......谢谢!

3 个答案:

答案 0 :(得分:1)

您需要考虑Contact.Name LIKE'%o%'可能会返回多个唯一名称

否则左边的值也可以使用连接

select top 100 * 
from
(
SELECT dbo.Customer.Number, 
       dbo.Contact.Name, 
       dbo.Address.StreetAddress, 
       row_number() over (partition by dbo.Customer.Number order dbo.Address.Order) as rn
  FROM dbo.Customer 
  JOIN dbo.Contact 
        ON dbo.Contact.Id        = dbo.Customer.ContactId          
  JOIN dbo.Address 
        ON dbo.Address.ContactId = dbo.Customer.ContactId -- = dbo.Contact.Id   
 where Contact.Name LIKE '%o%' 
    or Address.StreetAddress LIKE '%o%'
) tt 
where tt.rn = 1
order by tt.Customer.Number

我认为你可以通过dbo.Customer.Number进行分区,但你可能需要添加dbo.Contact.Name和dbo.Address.StreetAddress

如果你想使用左边那么你需要
(Contact.Name LIKE'%o%'或Contact.Name为空)
和地址需要加入dbo.Customer.ContactId
获得空连接

答案 1 :(得分:0)

如果您始终需要基于地址表中排序顺序的单个记录,只需按该字段对结果进行排序,并将结果限制为TOP (1)而不是TOP(100)。

SELECT TOP (1)  
    dbo.Customer.Number, dbo.Contact.Name, 
    dbo.Address.StreetAddress, dbo.Address.Order 
FROM
    dbo.Customer 
LEFT JOIN
    dbo.Contact ON dbo.Customer.ContactId = dbo.Contact.Id 
LEFT JOIN
    dbo.Address ON dbo.Contact.Id = dbo.Address.ContactId
WHERE
    Contact.Name LIKE '%o%' OR Address.StreetAddress LIKE '%o%'
ORDER BY dbo.Address.Order ASC

答案 2 :(得分:0)

如果您计划检索多个客户,但只有每个客户的主要地址,您可以在子查询中使用row_number(),并且只返回每个分区(客户)的第1行,如下所示:

SELECT dbo.Customer.Number,
       dbo.Contact.Name,
       dbo.Address.StreetAddress,
   dbo.Address.Order
  FROM (SELECT TOP (100) Row_number()
                           OVER (
                             partition BY dbo.Customer.Number, dbo.Contact.Name
                             ORDER BY dbo.Address.Order) AS seq,
                         dbo.Customer.Number,
                         dbo.Contact.Name,
                         dbo.Address.StreetAddress,
                         dbo.Address.Order
          FROM dbo.Customer
               LEFT JOIN dbo.Contact
                      ON dbo.Customer.ContactId = dbo.Contact.Id
               LEFT JOIN dbo.Address
                      ON dbo.Contact.Id = dbo.Address.ContactId
     WHERE Contact.Name LIKE '%o%'
        OR Address.StreetAddress LIKE '%o%') t
 WHERE t.seq = 1