基于 SQL Server 2008 中列值的内部联接
Posted
技术标签:
【中文标题】基于 SQL Server 2008 中列值的内部联接【英文标题】:Inner Join based on column value in SQL Server 2008 【发布时间】:2015-02-03 23:11:43 【问题描述】:我想根据列值连接两个表
如果pm.ServiceLevelID
的值为1 或NULL
,则在u.FacilityId
上进行内连接
如果pm.ServiceLevelID
的值为2,则在u.FacilityServiceId
上进行内连接
pm, u
这两个表有这些列:
ProviderMessages
MessageID, FacilityServiceID, ServiceLevelID, FacilityID, ProviderTypeID
User_FA
FacilityServiceId, UserFacilityID, FacilityId
目前,我有这个INNER JOIN
SELECT DISTINCT
MessageID, UserFacilityID, 9
FROM
#ProviderMessages
INNER JOIN
#User_FA ON (#User_FA.FacilityId = #ProviderMessages.FacilityID OR
#ProviderMessages.FacilityID IS NULL)
AND (#User_FA.FacilityServiceId = #ProviderMessages.FacilityServiceID)
【问题讨论】:
使用Case 我想知道这个问题有什么不好。 -5,真的吗? 【参考方案1】:SELECT DISTINCT MessageID, UserFacilityID, 9
FROM #ProviderMessages
JOIN #User_FA
ON #ProviderMessages.ServiceLevelID in (null,1,2)
and ( ( #ProviderMessages.ServiceLevelID in (null,1)
and #User_FA.FacilityId = #ProviderMessages.FacilityID)
or
( ProviderMessages.ServiceLevelID = 2
AND #User_FA.FacilityServiceId = #ProviderMessages.FacilityServiceID)
)
【讨论】:
添加子句#ProviderMessages,ServiceLevelID in (null,1,2) and
有什么好处?
@Beth 我认为这不会造成伤害。而且我认为它可以让查询优化器提前抛出一些东西。
猜这取决于规模。不过,我怀疑还有其他价值。
@Beth 为什么猜?检查查询计划。它要么在 ServiceLevelID 早期进行索引搜索,要么不进行。更快的查询没有价值?【参考方案2】:
这是您的查询,使用表别名使其更具可读性:
SELECT DISTINCT MessageID, UserFacilityID, 9
FROM #ProviderMessages m INNER JOI
#User_FA u
ON (u.FacilityId = m.FacilityID OR m.FacilityID IS NULL) AND
u.FacilityServiceId = m.FacilityServiceID;
你想要的逻辑是
SELECT DISTINCT MessageID, UserFacilityID, 9
FROM #ProviderMessages m INNER JOIN
#User_FA u
ON ((pm.ServiceLevelID = 1 or pm.ServiceLevelID is null) AND pm.FacilityId = u.facilityId) or
(pm.ServiceLevelID = 2 and pm.FacilityServiceID = m.FacilityServiceID)
【讨论】:
输出怎么错了?这就是你所要求的。 输出是什么,你期望它是什么?一个简单的“这不是我想要的”并不能帮助任何人获得你真正想要的解决方案。【参考方案3】:我不确定我是否理解得很好,但在我之前的工作中,我们也遇到过类似的情况。 请试试这个:
SELECT DISTINCT
MessageID, UserFacilityID, 9
FROM
#ProviderMessages
INNER JOIN #User_FA
ON (CASE WHEN ISNULL(#ProviderMessages.ServiceLevelID, 1) = 1
THEN #ProviderMessages.FacilityID
ELSE #ProviderMessages.FacilityServiceId
END)
= (CASE WHEN ISNULL(#ProviderMessages.ServiceLevelID, 1) = 1
THEN #User_FA.FacilityId
ELSE #User_FA.FacilityServiceId
END)
希望对你有帮助。
【讨论】:
【参考方案4】:合并两个结果
SELECT DISTINCT MessageID, UserFacilityID, 9
FROM #ProviderMessages
INNER JOIN #User_FA ON (#User_FA.FacilityId = #ProviderMessages.FacilityID OR
#ProviderMessages.FacilityID IS NULL)
WHERE #ProviderMessages.ServiceLevel <> 2
UNION
SELECT DISTINCT MessageID, UserFacilityID, 9
FROM #ProviderMessages
INNER JOIN #User_FA ON (#User_FA.FacilityServiceId = #ProviderMessages.FacilityServiceID)
WHERE #ProviderMessages.ServiceLevel = 2
【讨论】:
以上是关于基于 SQL Server 2008 中列值的内部联接的主要内容,如果未能解决你的问题,请参考以下文章