比这更高效的联盟声明?

时间:2014-10-01 18:16:45

标签: sql tsql stored-procedures database-performance sql-execution-plan

我正在尝试连接一些通用搜索结果,并希望它能够像我可能实现的那样执行。它现在并不可怕,但我觉得我可能会改进这里的“where”部分,甚至将其缩小为单个where子句。我也担心随着数据库的增长,这将如何发挥作用。

我的问题是,是否有更好的方法将这些信息加在一起(当我们基本上重复使用类似的表子集时,联合所有的替代方法)。这些都是很好的索引,并且执行计划显示大部分成本分布相当均匀。

Select Distinct m.MLSDataId as ResultId, m.MLSNumber as ResultName, '#/mlsrecord/'+convert(varchar(20),m.MLSDataId) as ResultLink, a.StreetLine1 as Description, 'fa-home large' as Icon,
    IsNull(m.UpdateDate,m.CreateDate) as ModifiedDate, 'Property' as TypeName
    From MLSDatas m
    Inner Join Addresses a on a.AddressId = m.AddressFK 
    Left Join MLSContacts mc on mc.MLSDataFK = m.MlsDataId
    Left Join Contacts c on ContactId = ContactFK
    Left Join People p on PersonId = PersonFK
    Left Join MLSAgents ma on ma.MLSDataFK = m.MlsDataId
    Left Join Agents ag on ag.AgentId = ma.AgentFK
    Left Join People p2 on p2.PersonId = ag.PersonFK
    Left Join PersonPhones pp on pp.PersonFK = p.PersonId
    Left Join Phones ph on ph.PhoneId = pp.PhoneFK
    Left Join PersonEmails pe on pe.PersonFK = p.PersonId
    Left Join Emails e on e.EmailId = pe.EmailFK
    Where m.MLSNumber like '%'+@term+'%' or StreetLine1 like '%'+@term+'%' 
    or p.FirstName like '%'+@term+'%' or p.LastName like '%'+@term+'%' or p.FirstName + ' ' + p.LastName like '%'+@term+'%'
    or p2.FirstName like '%'+@term+'%' or p2.LastName like '%'+@term+'%' or p2.FirstName + ' ' + p2.LastName like '%'+@term+'%'
    or ph.PhoneNumber like '%'+@term+'%'
    or e.EmailAddress like '%'+@term+'%'

    Union ALL

    Select Distinct l.ListingId as ResultId, l.DisplayTitle as ResultName, '#/listing/'+convert(varchar(20),l.ListingId) as ResultLink, l.DisplayTitle as Description, 'fa-globe large' as Icon,
    IsNull(m.UpdateDate,m.CreateDate) as ModifiedDate, 'Listing' as TypeName
    From Listings l
    Inner Join MLSDatas m on m.MLSDataId = l.MLSDataFK
    Inner Join Addresses a on a.AddressId = m.AddressFK 
    Left Join MLSContacts mc on mc.MLSDataFK = MlsDataId
    Left Join Contacts c on ContactId = ContactFK
    Left Join People p on PersonId = PersonFK
    Left Join PersonPhones pp on pp.PersonFK = p.PersonId
    Left Join Phones ph on ph.PhoneId = pp.PhoneFK
    Left Join PersonEmails pe on pe.PersonFK = p.PersonId
    Left Join Emails e on e.EmailId = pe.EmailFK
    Where m.MLSNumber like '%'+@term+'%' or StreetLine1 like '%'+@term+'%' 
    or p.FirstName like '%'+@term+'%' or p.LastName like '%'+@term+'%' or p.FirstName + ' ' + p.LastName like '%'+@term+'%'
    or ph.PhoneNumber like '%'+@term+'%'
    or e.EmailAddress like '%'+@term+'%'

    Union All

    Select Distinct c.ContactId as ResultId, p.FirstName + ' ' + p.LastName as ResultName, '#/contact/'+convert(varchar(20),c.ContactId) as ResultLink, p.FirstName + ' ' + p.LastName as Description, 'fa-book large' as Icon,
    IsNull(p.UpdateDate,p.CreateDate) as ModifiedDate, 'Contact' as TypeName
    From MLSDatas m
    Inner Join Addresses a on a.AddressId = m.AddressFK 
    Left Join MLSContacts mc on mc.MLSDataFK = m.MlsDataId
    Left Join Contacts c on ContactId = ContactFK
    Left Join People p on PersonId = PersonFK
    Left Join PersonPhones pp on pp.PersonFK = p.PersonId
    Left Join Phones ph on ph.PhoneId = pp.PhoneFK
    Left Join PersonEmails pe on pe.PersonFK = p.PersonId
    Left Join Emails e on e.EmailId = pe.EmailFK
    Where m.MLSNumber like '%'+@term+'%' or StreetLine1 like '%'+@term+'%' 
    or p.FirstName like '%'+@term+'%' or p.LastName like '%'+@term+'%' or p.FirstName + ' ' + p.LastName like '%'+@term+'%'
    or ph.PhoneNumber like '%'+@term+'%'
    or e.EmailAddress like '%'+@term+'%'

    Union All

    Select Distinct ag.AgentId as ResultId, p.FirstName + ' ' + p.LastName as ResultName, '#/agent/'+convert(varchar(20),ag.AgentId) as ResultLink, p.FirstName + ' ' + p.LastName as Description, 'fa-suitcase large' as Icon,
    IsNull(p.UpdateDate,p.CreateDate) as ModifiedDate, 'Agent' as TypeName
    From MLSDatas m
    Inner Join Addresses a on a.AddressId = m.AddressFK 
    Left Join MLSAgents ma on ma.MLSDataFK = m.MlsDataId
    Left Join Agents ag on ag.AgentId = ma.AgentFK
    Left Join People p on PersonId = ag.PersonFK
    Left Join PersonPhones pp on pp.PersonFK = p.PersonId
    Left Join Phones ph on ph.PhoneId = pp.PhoneFK
    Left Join PersonEmails pe on pe.PersonFK = p.PersonId
    Left Join Emails e on e.EmailId = pe.EmailFK
    Where m.MLSNumber like '%'+@term+'%' or StreetLine1 like '%'+@term+'%' 
    or p.FirstName like '%'+@term+'%' or p.LastName like '%'+@term+'%' or p.FirstName + ' ' + p.LastName like '%'+@term+'%'
    or ph.PhoneNumber like '%'+@term+'%'
    or e.EmailAddress like '%'+@term+'%'

提前致谢!

2 个答案:

答案 0 :(得分:-1)

很多问题 你打破了左边的

你可以把它带到#temp中,这样它只被评估一次 但是因为你并不总是标记表格我不得不做一些猜测 然后你加入#temp
并在#Temp上声明PK,因为它应该有助于查询优化器

insert into #temp (ID)
select m.MLSDataId   
  from MLSDatas m --
  Join People p on PersonId = PersonFK  --
  Join PersonPhones pp on pp.PersonFK = p.PersonId
  Join Phones ph on ph.PhoneId = pp.PhoneFK  --
  Join PersonEmails pe on pe.PersonFK = p.PersonId
  Join Emails e on e.EmailId = pe.EmailFK --  
Where m.MLSNumber like '%'+@term+'%' 
   or p.FirstName like '%'+@term+'%' 
   or p.LastName like '%'+@term+'%' 
   or p.FirstName + ' ' + p.LastName like '%'+@term+'%'
   or ph.PhoneNumber like '%'+@term+'%'
   or e.EmailAddress like '%'+@term+'%'


...
From Listings l 
join #temp as m 
  on m.MLSDataId = l.MLSDataFK

  on #tempID = 

答案 1 :(得分:-1)

我建议使用CTE,但正如我在上面的评论中提到的,您应该考虑对数据库设计进行非规范化。即使,此数据库中的人(姓名等)也可以应用于用户,员工,代理,联系人或其他人员。该问题的一个建议是使用类型(例如,用户,员工,代理,联系人或其他)。关于,"让下一个走进来的人更容易识别外键指向的位置",我也许不知道。但是,它看起来确实非常混乱。你最后的选择。

如果你最终没有反规范化,我建议这就是:

with cte_noWhere as
(
Select Distinct m.MLSDataId as ResultId, m.MLSNumber as ResultName, '#/mlsrecord/'+convert(varchar(20),m.MLSDataId) as ResultLink, a.StreetLine1 as Description, 'fa-home large' as Icon,
IsNull(m.UpdateDate,m.CreateDate) as ModifiedDate, 'Property' as TypeName,
m.MLSNumber as MLSNumber, StreetLine1, p.FirstName as FirstName, p.LastName as LastName, ph.PhoneNumber,
e.EmailAddress
From MLSDatas m
Inner Join Addresses a on a.AddressId = m.AddressFK 
Left Join MLSContacts mc on mc.MLSDataFK = m.MlsDataId
Left Join Contacts c on ContactId = ContactFK
Left Join People p on PersonId = PersonFK
Left Join MLSAgents ma on ma.MLSDataFK = m.MlsDataId
Left Join Agents ag on ag.AgentId = ma.AgentFK
Left Join People p2 on p2.PersonId = ag.PersonFK
Left Join PersonPhones pp on pp.PersonFK = p.PersonId
Left Join Phones ph on ph.PhoneId = pp.PhoneFK
Left Join PersonEmails pe on pe.PersonFK = p.PersonId
Left Join Emails e on e.EmailId = pe.EmailFK
Where p2.FirstName like '%'+@term+'%' or p2.LastName like '%'+@term+'%' or p2.FirstName + ' ' + p2.LastName like '%'+@term+'%'

Union ALL

Select Distinct l.ListingId as ResultId, l.DisplayTitle as ResultName, '#/listing/'+convert(varchar(20),l.ListingId) as ResultLink, l.DisplayTitle as Description, 'fa-globe large' as Icon,
IsNull(m.UpdateDate,m.CreateDate) as ModifiedDate, 'Listing' as TypeName,
m.MLSNumber as MLSNumber, StreetLine1, p.FirstName as FirstName, p.LastName as LastName, ph.PhoneNumber,
e.EmailAddress
From Listings l
Inner Join MLSDatas m on m.MLSDataId = l.MLSDataFK
Inner Join Addresses a on a.AddressId = m.AddressFK 
Left Join MLSContacts mc on mc.MLSDataFK = MlsDataId
Left Join Contacts c on ContactId = ContactFK
Left Join People p on PersonId = PersonFK
Left Join PersonPhones pp on pp.PersonFK = p.PersonId
Left Join Phones ph on ph.PhoneId = pp.PhoneFK
Left Join PersonEmails pe on pe.PersonFK = p.PersonId
Left Join Emails e on e.EmailId = pe.EmailFK

Union All

Select Distinct c.ContactId as ResultId, p.FirstName + ' ' + p.LastName as ResultName, '#/contact/'+convert(varchar(20),c.ContactId) as ResultLink, p.FirstName + ' ' + p.LastName as Description, 'fa-book large' as Icon,
IsNull(p.UpdateDate,p.CreateDate) as ModifiedDate, 'Contact' as TypeName,
m.MLSNumber as MLSNumber, StreetLine1, p.FirstName as FirstName, p.LastName as LastName, ph.PhoneNumber,
e.EmailAddress
From MLSDatas m
Inner Join Addresses a on a.AddressId = m.AddressFK 
Left Join MLSContacts mc on mc.MLSDataFK = m.MlsDataId
Left Join Contacts c on ContactId = ContactFK
Left Join People p on PersonId = PersonFK
Left Join PersonPhones pp on pp.PersonFK = p.PersonId
Left Join Phones ph on ph.PhoneId = pp.PhoneFK
Left Join PersonEmails pe on pe.PersonFK = p.PersonId
Left Join Emails e on e.EmailId = pe.EmailFK

Union All

Select Distinct ag.AgentId as ResultId, p.FirstName + ' ' + p.LastName as ResultName, 
'#/agent/'+convert(varchar(20),ag.AgentId) as ResultLink, p.FirstName + ' ' + p.LastName as Description, 
'fa-suitcase large' as Icon,
IsNull(p.UpdateDate,p.CreateDate) as ModifiedDate, 'Agent' as TypeName,
m.MLSNumber as MLSNumber, StreetLine1, p.FirstName as FirstName, p.LastName as LastName, ph.PhoneNumber,
e.EmailAddress
From MLSDatas m
Inner Join Addresses a on a.AddressId = m.AddressFK 
Left Join MLSAgents ma on ma.MLSDataFK = m.MlsDataId
Left Join Agents ag on ag.AgentId = ma.AgentFK
Left Join People p on PersonId = ag.PersonFK
Left Join PersonPhones pp on pp.PersonFK = p.PersonId
Left Join Phones ph on ph.PhoneId = pp.PhoneFK
Left Join PersonEmails pe on pe.PersonFK = p.PersonId
Left Join Emails e on e.EmailId = pe.EmailFK
)
select *
from cte_noWhere w
Where w.MLSNumber like '%'+@term+'%' or w.StreetLine1 like '%'+@term+'%' 
    or w.FirstName like '%'+@term+'%' 
        or w.LastName like '%'+@term+'%' or w.FirstName + ' ' + w.LastName like '%'+@term+'%'
    or w.PhoneNumber like '%'+@term+'%'
    or w.EmailAddress like '%'+@term+'%'

我在CTE中使用了大部分代码并提取了common where子句。这可能会更快,更有效,但我不确定。如果是,那么可能是因为你现在做了一个where子句而不是4.