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

Jus*_*ner 118 sql sql-server join case

以下图像是Microsoft SQL Server 2008 R2系统视图的一部分.从图片我们可以看到,之间的关系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 
Run Code Online (Sandbox Code Playgroud)

但是上面的代码给出了语法错误.我猜这是因为CASE声明.任何人都可以帮忙解释一下吗?

谢谢!


添加错误消息:

消息102,级别15,状态1,行6'='附近的语法不正确.

这是图像

HAB*_*ABO 202

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
Run Code Online (Sandbox Code Playgroud)

请注意,您需要对返回的值执行某些操作,例如将其与1进行比较.您的语句尝试返回赋值或测试的相等值,这两者在CASE/ THEN子句的上下文中都没有意义.(如果BOOLEAN是数据类型,那么相等的测试是有意义的.)

  • @SagarTandel - 来自[MSDN](http://technet.microsoft.com/en-us/library/ms181765.aspx?ppud=4):"CASE语句按顺序评估其条件,并以条件为的第一个条件停止满意.".如果您希望所有连接的行与任何明确说明的条件都不匹配,只需将尾端从`= 1`更改为`= 0`,但我不认为您会喜欢结果. (3认同)

Nir*_*ngh 32

相反,您只需加入两个表,并在SELECT子句中返回匹配的数据:

我建议你在JOIN ON子句中浏览SQL ServerT-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 
Run Code Online (Sandbox Code Playgroud)

编辑:根据评论.

你不能像你一样指定连接条件.检查上面没有错误的查询.我已经取出了公共列,并且将根据条件评估右列值.


ric*_*ent 17

试试这个:

...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)
Run Code Online (Sandbox Code Playgroud)


Don*_*ong 8

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

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             
Run Code Online (Sandbox Code Playgroud)

这是因为:

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


小智 5

我拿了你的例子并编辑了它:

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)
Run Code Online (Sandbox Code Playgroud)


Ste*_*bor 5

是的你可以。这是一个例子。

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 
Run Code Online (Sandbox Code Playgroud)