允许同一个表的多个左外连接?

Posted

技术标签:

【中文标题】允许同一个表的多个左外连接?【英文标题】:Multiple left outer join with same table allowed? 【发布时间】:2012-03-14 11:22:05 【问题描述】:

我尝试以更优化的方式在 SQL 下进行转换,但它给出了错误“操作数类型冲突:uniqueidentifier 与 int 不兼容”。你能帮帮我吗

select E.EHOId, E.ReferenceId 'ReferenceNo',
(select Comp_Name from FoodAlertCRM.dbo.vCompanyPE where Comp_CompanyId = E.GroupId) 'Group',
(select Comp_Name from FoodAlertCRM.dbo.vCompanyPE where Comp_CompanyId = E.SiteId) 'Site',
 E.VisitDate as 'VisitDate',
(select Name from EHO_Dropdowns where ID = E.FollowupAction) 'FollowupAction',
(select Name from EHO_LocalAuthority where ID = E.LocalAuthority) 'LocalAuthority',
(select Name from EHO_Dropdowns where ID = E.[Status]) 'Status', 
(select Name from EHO_Dropdowns where ID = E.Position) 'Position',
(select Name from EHO_Dropdowns where ID = E.Structural) 'Structural',
(select Name from EHO_Dropdowns where ID = E.ConfidenceinManagement) 'ConfideninManagement',
(select Name from EHO_Dropdowns where ID = E.HygieneandSafety) 'HygieneandSafety',
(select Name from EHO_Dropdowns where ID = E.RoutineInspection) 'RoutineInspection',
(select Name from EHO_Dropdowns where ID = E.OutcomeofVisit) 'OutcomeofVisit',
e.OfficerName,e.FoodHygieneRating,e.ManageronDuty,e.Comments,
CASE E.AnnouncedVisit
 When  0 Then 'No'
 When 1 Then 'Yes'
 Else ''
ENd as 'AnnouncedVisit',
(select u.Username from FoodAlertCRM.dbo.CDB_User u where u.UserId = e.CreatedBy ) 'CreatedBy',
(select COUNT(EHOId) from EHO_Attachments where EHOId = E.EHOId) as 'AttachmentCount'
from EHO_Log E
where E.IsActive = 1 AND e.IsDeleted = 0 
Order by E.VisitDate desc

你看到上面有很多内部查询,如果有一千条记录,性能会很差。所以我试图摆脱内部查询。

select E.EHOId, E.ReferenceId 'ReferenceNo',
(select Comp_Name from FoodAlertCRM.dbo.vCompanyPE where Comp_CompanyId = E.GroupId) 'Group',
(select Comp_Name from FoodAlertCRM.dbo.vCompanyPE where Comp_CompanyId = E.SiteId) 'Site',
 E.VisitDate as 'VisitDate',
F.Name 'FollowupAction',L.Name 'LocalAuthority', St.Name 'Status',
P.Name 'Position', S.Name 'Structural', C.Name 'ConfideninManagement',
H.Name 'HygieneandSafety', R.Name 'RoutineInspection', O.Name 'OutcomeofVisit',
e.OfficerName,e.FoodHygieneRating,e.ManageronDuty,e.Comments,
CASE E.AnnouncedVisit
 When  0 Then 'No'
 When 1 Then 'Yes'
 Else ''
ENd as 'AnnouncedVisit',
(select u.Username from FoodAlertCRM.dbo.CDB_User u where u.UserId = e.CreatedBy ) 'CreatedBy',
(select COUNT(EHOId) from EHO_Attachments where EHOId = E.EHOId) as 'AttachmentCount'
from EHO_Log E
Left Outer Join EHO_Dropdowns St ON St.Id = E.[Status]
Left Outer Join EHO_Dropdowns F ON F.Id = E.FollowupAction
Left Outer Join EHO_Dropdowns L ON L.Id = E.LocalAuthority
Left Outer Join EHO_Dropdowns P ON P.Id = E.Position
Left Outer Join EHO_Dropdowns S ON S.Id = E.Structural
Left Outer Join EHO_Dropdowns C ON C.Id = E.ConfidenceinManagement
Left Outer Join EHO_Dropdowns H ON H.Id = E.HygieneandSafety
Left Outer Join EHO_Dropdowns R ON R.Id = E.RoutineInspection
Left Outer Join EHO_Dropdowns O ON O.Id = E.OutcomeofVisit
where E.IsActive = 1 AND e.IsDeleted = 0 
Order by E.VisitDate desc

以上代码失败,我认为不允许多个左外连接,我将其转换为以下查询,但仍然失败

select E.EHOId, E.ReferenceId 'ReferenceNo',
(select Comp_Name from FoodAlertCRM.dbo.vCompanyPE where Comp_CompanyId = E.GroupId) 'Group',
(select Comp_Name from FoodAlertCRM.dbo.vCompanyPE where Comp_CompanyId = E.SiteId) 'Site',
 E.VisitDate as 'VisitDate',
D.Name 'FollowupAction',D.Name 'LocalAuthority', D.Name 'Status',
D.Name 'Position', D.Name 'Structural', D.Name 'ConfideninManagement',
D.Name 'HygieneandSafety', D.Name 'RoutineInspection', D.Name 'OutcomeofVisit',
e.OfficerName,e.FoodHygieneRating,e.ManageronDuty,e.Comments,
CASE E.AnnouncedVisit
 When  0 Then 'No'
 When 1 Then 'Yes'
 Else ''
ENd as 'AnnouncedVisit',
(select u.Username from FoodAlertCRM.dbo.CDB_User u where u.UserId = e.CreatedBy ) 'CreatedBy',
(select COUNT(EHOId) from EHO_Attachments where EHOId = E.EHOId) as 'AttachmentCount'
from EHO_Log E
Left Outer Join EHO_Dropdowns D ON D.Id = E.[Status] AND D.Id = E.FollowupAction
AND D.Id = E.LocalAuthority AND D.Id = E.Position AND D.Id = E.Structural
AND D.Id = E.ConfidenceinManagement AND D.Id = E.HygieneandSafety
AND D.Id = E.RoutineInspection AND D.Id = E.OutcomeofVisit
where E.IsActive = 1 AND e.IsDeleted = 0 
Order by E.VisitDate desc

有什么想法吗?两个新查询都返回错误“操作数类型冲突:uniqueidentifier 与 int 不兼容”。

【问题讨论】:

新查询以什么方式失败?它们是否产生了错误,如果是,它们是什么?它们是否运行没有错误,但未能产生所需的数据,如果是,结果以什么方式出错? 两个新查询都失败并给我错误“操作数类型冲突:uniqueidentifier 与 int 不兼容”。 【参考方案1】:

我认为原因可能是这一行:

Left Outer Join EHO_Dropdowns L ON L.Id = E.LocalAuthority

尝试将其更改为:

Left Outer Join EHO_LocalAuthority L ON L.Id = E.LocalAuthority

【讨论】:

太糟糕了,我怎么能错过这个。你是绝对正确的,但你是如何设法从所有表格中检查出来的。 :) 你能告诉我使用这么多左外部而不是内部查询是否经过优化?谢谢 似乎最后一个在左外连接中有 AND 子句的查询未能产生正确的结果,它给出了 NULL,如果我做 OR,那么它给出了多条记录或两倍的大小。所以第二个是最好的选择? @KamranPervaiz:我更喜欢第二个查询。合理确定哪一个是性能更好的方法的唯一方法是尝试针对实际数据集运行这两个查询,看看哪个性能更好。我见过作者想要强制优化器在子查询表上使用索引的地方使用的子查询方法;但是,这可能会阻止优化器使用比索引多次访问更快的单表扫描。如果子查询之一曾经返回多个值,则子查询方法也可能会失败。 谢谢,但它没有显示正确的结果。如果存在,所有左外连接结果都返回 NULL 或 Othername。虽然记录中有正确的数据但显示为NULL?有什么想法吗? 抱歉,它现在正在工作。每个 When 语句中都应该有一个 else 情况,例如 Else R.Name 等【参考方案2】:

同一张表上的多个外连接:

解决方案:

请在外连接字段上使用 nvl

NVL(EHO_Dropdowns(+),EHO_LocalAuthority(+)) = E.LocalAuthority

【讨论】:

以上是关于允许同一个表的多个左外连接?的主要内容,如果未能解决你的问题,请参考以下文章

左外连接和右外连接的区别

每组右表的左外连接?

Linq to Sql:多个左外连接

LINQ:具有多个条件的左外连接

内连接与左外链接的区别

Linq to Entity 具有多个左外连接