Sql 比这更有效的工会声明?
我正在尝试连接一些通用的搜索结果,并希望它能够像我可能做到的那样执行。现在并不可怕,但我觉得我有可能改进其中的“where”部分,甚至可以将其浓缩为一个where子句。我还担心随着时间的推移,随着数据库的增长,这将如何执行 我的问题是,是否有更好的方法将这些信息连接在一起(当我们基本上重复使用相似的表子集时,这是UNIONALL的替代方法)。所有这些都有很好的索引,执行计划显示大部分成本分布相当均匀Sql 比这更有效的工会声明?,sql,tsql,stored-procedures,database-performance,sql-execution-plan,Sql,Tsql,Stored Procedures,Database Performance,Sql Execution Plan,我正在尝试连接一些通用的搜索结果,并希望它能够像我可能做到的那样执行。现在并不可怕,但我觉得我有可能改进其中的“where”部分,甚至可以将其浓缩为一个where子句。我还担心随着时间的推移,随着数据库的增长,这将如何执行 我的问题是,是否有更好的方法将这些信息连接在一起(当我们基本上重复使用相似的表子集时,这是UNIONALL的替代方法)。所有这些都有很好的索引,执行计划显示大部分成本分布相当均匀 Select Distinct m.MLSDataId as ResultId, m.MLSNu
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+'%'
提前谢谢 很多问题你在何处向左拐 您可以将其带到一个#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 =
我建议使用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这可能不是你的错,但你应该考虑对数据库进行反编译。当然,你可以更轻松地查询它。有很多多对多的关系,我们也在实体框架中使用它。地址/电话/电子邮件/人员/等存储一次。命名约定在很大程度上也是关系性的,这使得下一个进来的人更容易识别外键指向的位置。。。当此数据库中的一个人(名字和姓氏等)可以应用于用户、员工、代理、联系人或其他人时,非规范化成为一个真正令人头痛的问题。。同一个人很可能同时是这些实体中的一个或两个以上。我明白你的观点,但我不同意。您的代码看起来非常凌乱和笨重,这主要是由于它的设计。即使去规范化是痛苦的,但在未来它将是一个巨大的好处。在我的回答中我还包括了一些反馈(关于你为什么不去规范化你的数据库的原因)。希望有帮助。您担心性能问题,并在相同的加载时间内检查了解决方案。我的答案是-1。我没有考虑过CTE。我试一试,它的加载时间几乎相同(>1秒),虽然更干净(所以我就买它)。关于类型字段,这仍然允许使用多行相同的名称,这是我一直试图避免的。当一个人有多部电话和电子邮件时,这些电话和电子邮件不会与你建议的独特类型的每一行联系起来。此外,此模式在C#应用程序中运行良好,因为用户继承了“Person”类型,其他Person类型的实体也是如此。这看起来太复杂了,但它有很多原因。。。我排完了队。。。感谢您抽出时间回答。我仍在权衡数据库设计的选择,但我们有一位客户,在我引用该应用程序之前大约6个月,他就承诺了这个应用程序。。。“所以我现在有点时间紧张了。”布拉德尔,我完全理解。我去过那里,做过那件事。我只是觉得你应该知道其他方法,以及为什么另一种方法可能会更好。如果我的答案有帮助,请向上投票或单击复选标记选择答案,我们将不胜感激。:)祝你好运。cte只是语法。你能详细说明你的观点吗?不知道你是什么意思。不是我说的。@PaulKar。我没有投你反对票。即使我不认为你的回答有效率。在查看并思考了你的回答后,我似乎看不出有几个表格(例如地址、MLS联系人、联系人、MLS联系人、代理)去了哪里?除此之外,当Brad使用更多列时,您仅选择一列。看来你的答案不完整。@PaulKar。我需要画画吗?你把它变成临时工,然后加入临时工4次#temp是具体化的,只计算一次。困难的事情只能做一次。如果OP甚至不打算标记c0me列来自哪个表并提供MLSDatas的定义,我就不会花更多的精力。