客户表
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中执行此操作?顺便说一句,我的目标也是尽可能快地得到结果,还有其他方法可以在“一对多”连接表中进行这种搜索吗?
我只需要一些东西......谢谢!
答案 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