【问题标题】:using CASE WHEN after CTE在 CTE 之后使用 CASE WHEN
【发布时间】:2018-12-23 16:25:08
【问题描述】:

我试图在 CTE 定义之后立即使用 CASE WHEN,但查询只需要 SELECT

WITH A AS
(...) --long query here
CASE WHEN @parameter = '' THEN
SELECT * FROM A 
ELSE
SELECT * FROM A WHERE field like '%' + @parameter + '%'
END

除了使用OR 语句之外,还有其他方法可以使这个查询工作吗?

【问题讨论】:

  • “除了使用 OR 语句” - UNION
  • 为什么要使用CASE 来确定选择?为什么不是IF/ELSE
  • 如果您从某个应用程序运行此查询并在那里定义@parameter,则在将查询发送到数据库之前在应用程序端执行此逻辑。
  • @dbajtr IF 在这里也不起作用
  • @Fabio 如果@parameter 不为空,我不想将整个结果集发送到应用程序

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


【解决方案1】:

首先,您使用 CASE WHEN 错误。它应该用于返回单个值,而不是表,例如作为 select 子句的一部分。它不打算用作流控制来运行两个查询之一。为此使用 IF。

其次,您不能从选择中拆分 CTE,它是同一语句的一部分。你不能说“这是一个 CTE,现在从中运行两个语句之一”,这不是 CTE 语句的编写方式。您可以在一个选择中多次重复使用 CTE,但要运行整个选择,而不仅仅是其中的一部分。

一些可行的替代方法

您可以在整个查询周围使用 IF,并将其写出两次。这样只有一个版本的查询实际运行。

IF @parameter = ''
    SELECT (your query here)
ELSE
    SELECT (your query here) WHERE field like ...

您可以使用动态 SQL,将查询的第一部分构建为字符串。然后只在需要时添加 where 子句,然后运行生成的 SQL。

【讨论】:

    【解决方案2】:

    您可以在WHERE 子句中使用OR

    WITH A AS
        (...) --long query here
    SELECT *
    FROM A
    WHERE (field like '%' + @parameter + '%') OR @parameter = '';
    

    如果field 永远不是NULL,那么这相当于:

    WITH A AS
        (...) --long query here
    SELECT *
    FROM A
    WHERE field like '%' + @parameter + '%';
    

    LIKE '%%' 匹配任何非空字符串。)

    【讨论】:

    • @YevgeniGrinberg 。 . . like 模式以通配符开头,我很惊讶对性能的影响是显而易见的。
    • 使用OR,优化器将忽略@parameter = '' 条件并构建一个计划,对表中的每一行进行比较。当@parameter 为空时,我想避免它。
    • @YevgeniGrinberg 。 . .我的观点是,这两个版本的查询都会进行全表扫描。这通常比like 贵得多——尽管如果您的字符串很长,则字符串操作可能会开始累加。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 2014-11-29
    • 2022-01-10
    • 2021-01-24
    • 1970-01-01
    相关资源
    最近更新 更多