我可以在 JOIN 条件下使用 CASE 语句吗?

下面的图片是2008年 R2系统视图 Microsoft SQL Server 的一部分。从图像中我们可以看到,sys.partitionssys.allocation_units之间的关系取决于 sys.allocation_units.type的值。因此,为了将它们联系起来,我会写一些类似的东西:

SELECT  *
FROM    sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON CASE
WHEN a.type IN (1, 3)
THEN a.container_id = p.hobt_id
WHEN a.type IN (2)
THEN a.container_id = p.partition_id
END

但是上面的代码出现了语法错误,我猜这是因为 CASE语句。 有人能解释一下吗?


添加错误消息:

Msg 102,等级15,状态1,第6行’=’附近语法不正确。

this is the image

661359 次浏览

试试这个:

...JOIN sys.allocation_units a ON
(a.type=2 AND a.container_id = p.partition_id)
OR (a.type IN (1, 3) AND a.container_id = p.hobt_id)

相反,您只需连接到这两个表,并在您的 SELECT 子句中, 返回匹配的数据:

我建议你通过这个链接 SQLServer 中的条件连接JOIN ON 子句中的 T-SQL Case 语句

例如:。

    SELECT  *
FROM    sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON a.container_id =
CASE
WHEN a.type IN (1, 3)
THEN  p.hobt_id
WHEN a.type IN (2)
THEN p.partition_id
END

编辑: 根据评论。

不能按照正在执行的操作指定连接条件。请检查 上面的查询没有错误。我已经删除了公共列向上 将根据条件计算右列值。

CASE表达式从子句的 THEN部分返回一个值。您可以这样使用它:

SELECT  *
FROM    sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON CASE
WHEN a.type IN (1, 3) AND a.container_id = p.hobt_id THEN 1
WHEN a.type IN (2) AND a.container_id = p.partition_id THEN 1
ELSE 0
END = 1

注意,您需要对返回的值执行某些操作,例如,将它与1进行比较。您的语句试图返回赋值或相等性测试的值,这两种方法在 CASE/THEN子句的上下文中都没有意义。(如果 BOOLEAN是一个数据类型,那么相等性测试就有意义了。)

这看起来不错

Https://bytes.com/topic/sql-server/answers/881862-joining-different-tables-based-condition

FROM YourMainTable
LEFT JOIN AirportCity DepCity ON @TravelType = 'A' and DepFrom =  DepCity.Code
LEFT JOIN AirportCity DepCity ON @TravelType = 'B' and SomeOtherColumn = SomeOtherColumnFromSomeOtherTable

在这里,我比较了两个不同结果集的差异:

SELECT main.ColumnName, compare.Value PreviousValue,  main.Value CurrentValue
FROM
(
SELECT 'Name' AS ColumnName, 'John' as Value UNION ALL
SELECT 'UserName' AS ColumnName, 'jh001' as Value UNION ALL
SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
SELECT 'Phone' AS ColumnName, NULL as Value UNION ALL
SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
SELECT 'IsActive' AS ColumnName, '1' as Value
) main
INNER JOIN
(
SELECT 'Name' AS ColumnName, 'Rahul' as Value UNION ALL
SELECT 'UserName' AS ColumnName, 'rh001' as Value UNION ALL
SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
SELECT 'Phone' AS ColumnName, '01722112233' as Value UNION ALL
SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
SELECT 'IsActive' AS ColumnName, '1' as Value
) compare
ON main.ColumnName = compare.ColumnName AND
CASE
WHEN main.Value IS NULL AND compare.Value IS NULL THEN 0
WHEN main.Value IS NULL AND compare.Value IS NOT NULL THEN 1
WHEN main.Value IS NOT NULL AND compare.Value IS NULL THEN 1
WHEN main.Value <> compare.Value THEN 1
END = 1

我采用了你的例子并编辑了它:

SELECT  *
FROM    sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON a.container_id = (CASE
WHEN a.type IN (1, 3)
THEN p.hobt_id
WHEN a.type IN (2)
THEN p.partition_id
ELSE NULL
END)

我认为你需要两个案例陈述:

SELECT  *
FROM    sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON
-- left side of join on statement
CASE
WHEN a.type IN (1, 3)
THEN a.container_id
WHEN a.type IN (2)
THEN a.container_id
END
=
-- right side of join on statement
CASE
WHEN a.type IN (1, 3)
THEN p.hobt_id
WHEN a.type IN (2)
THEN p.partition_id
END

这是因为:

  • CASE 语句返回 END 处的单个值
  • ON 语句比较两个值
  • 您的 CASE 语句正在进行 CASE 语句的 在里面比较。我猜想,如果您将 CASE 语句放在 SELECT 中,您将得到一个布尔值“1”或“0”,指示 CASE 语句的计算结果是 True 还是 False

以大金刚为例。

问题是我需要使用声明的变量。这允许陈述你需要比较的左边和右边。这是为了支持 SSRS 报告,其中不同的字段必须根据用户的选择进行链接。

初始大小写根据选定内容设置字段选择 然后我就可以为连接设置需要匹配的字段。

可以为右边添加第二个 case 语句,如果 变量需要从不同的字段中进行选择

LEFT OUTER JOIN Dashboard_Group_Level_Matching ON
case
when @Level  = 'lvl1' then  cw.Lvl1
when @Level  = 'lvl2' then  cw.Lvl2
when @Level  = 'lvl3' then  cw.Lvl3
end
= Dashboard_Group_Level_Matching.Dashboard_Level_Name

是的,你可以。这里有一个例子。

SELECT a.*
FROM TableA a
LEFT OUTER JOIN TableB j1 ON  (CASE WHEN LEN(COALESCE(a.NoBatiment, '')) = 3
THEN RTRIM(a.NoBatiment) + '0'
ELSE a.NoBatiment END ) = j1.ColumnName

根据条件,至少有两种加入方式,一种比另一种快:

declare @loopZaKosovnice int = 1
select *
from tHE_MoveItem mi
left join tHE_SetProdSt st on st.acIdent = mi.acIdent


-- slow
--join the_setitem si on si.acident = case when @loopZaKosovnice = 0 then mi.acident else st.acIdentChild end


-- two times as fast
left join the_setitem si1 on @loopZaKosovnice = 0 and si1.acident = mi.acident
left join the_setitem si2 on @loopZaKosovnice = 1 and si2.acident = st.acIdentChild
join the_setitem si on si.acident = isnull (si1.acident, si2.acIdent)