【问题标题】:IF Statements After CTE'sCTE 之后的 IF 语句
【发布时间】:2019-07-08 14:23:17
【问题描述】:

今天我遇到了一个与 IF 语句有关的奇怪问题。在我完成替换/创建 CTE 之后,我的 CTE 之后有 IF 语句,并且不断收到以下错误:

'if' 附近的语法不正确

查询:

-- Other CTE's above.
CTE6 AS 
(
    SELECT
        -- Multiple Columns
    FROM
        table1
)
-- When the Query runs, I'd like it to use the correct IF BLOCK.

-- Error starts here.
if @param_policy = '1' 
    select * from CTE4
    where mid not in (select distinct mid from CTE6)
        and [CN] = @param_policy

if @param_policy = '2' 
    select * from CTE4 
    where mid not in (select distinct mid from CTE6)
        and [CN] = @param_policy

if @param_policy = '3' 
    select * from CTE4 
    where mid not in (select distinct mid from CTE6)
        and [CN] = @param_policy                

if @param_policy = '4' 
    select * from CTE4 
    where mid not in (select distinct mid from CTE6)
        and [CN] = @param_policy   
-- UPDATED

select * from CTE4 WHERE @param_policy = 'batch' and mid not in (select distinct mid from CTE6)

and not
(([Client Number] ='5' and  Pnum = 'IN' )
or ([Client Number] ='6' and  Pnum = 'G')
or [Client Number] in ('7' , '8', '9')
)


还包括,当它执行select * from CTE4 时,它认为 CTE4 无效,并且它没有将“mid”识别为有效列。

我的 CTE 以前是临时表。

有人知道如何解决这个问题吗?

谢谢。

【问题讨论】:

  • 你的 4 个 SQL 看起来完全一样。如果是这样,你为什么需要if?如果不是这样,如果您向我们展示这些案例的实际差异,您可能会得到更好的答案。
  • 不幸的是,您用 CTE 替换临时表的想法需要您重新设计代码。简而言之,CTE 只能由单个语句引用。也许您应该重新使用临时表 - 根据不完整的代码和未知目标提出建议可能会产生误导。
  • @SMor OPENQUERY 不允许使用临时表,因此必须切换到 CTE。这是“重新设计”我的查询的唯一建议方法。
  • OPENQUERYFROM 子句中使用,因此不适用于IF 语句。更好的方法是从OPENQUERY 获取所有数据,然后在本地过滤。如果您确实需要在远程服务器上执行条件语句,请考虑使用EXEC AT
  • 这是 XY 问题的一个例子。 xyproblem.info

标签: sql-server tsql common-table-expression


【解决方案1】:

你可以这样做:

select *
from CTE4
where @param_policy in ('1', '2', '3', '4')  and
      mid not in (select distinct mid from CTE6) and
      [CN] = @param_policy;

IF 是 T-SQL 代码的控制流。它不是SELECT 查询语法的一部分。

更一般地说,你可以用union all做你想做的事:

select *
from CTE4
where @param_policy in ('1', '2', '3', '4')  and
      mid not in (select distinct mid from CTE6) and
      [CN] = @param_policy
union all
select *
from CTE4 
where @param_policy = 'batch' and
      mid not in (select distinct mid from CTE6) and
      not (([Client Number] ='5' and  Pnum = 'IN' ) or
           ([Client Number] ='6' and  Pnum = 'G') or
           ([Client Number] in ('7' , '8', '9')
          );

您也可以将这些条件添加到单个查询中,但我认为 union all 是您正在寻找的更通用的方法。

编辑:

或者,只是在WHERE 中使用更复杂的逻辑:

select *
from CTE4
where mid not in (select distinct mid from CTE6) and
      ( (@param_policy in ('1', '2', '3', '4')  and
         [CN] = @param_policy
         ) or
         (@param_policy = 'batch' and
          not (([Client Number] ='5' and  Pnum = 'IN' ) or
               ([Client Number] ='6' and  Pnum = 'G') or
               ([Client Number] in ('7' , '8', '9')
              )
         )
      )

【讨论】:

  • 嘿戈登,快速提问。什么是另一种方法而不是使用“联合所有”?我不太确定这是否会影响查询运行时间。还有其他建议吗? @戈登林诺夫
  • @LifeOfJona 。 . .对于基表,union all 通常会提供更多优化查询的机会(并非总是如此,但有时会如此)。使用 CTE,将为每个引用评估 CTE,这可能会使平衡回到在 where 子句中使用 or
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
相关资源
最近更新 更多