我是SQL的新手。
我已经为这个问题简化了一个复杂的SQL SELECT
语句。我继承代码并且需要避免过多地改变代码。
我需要添加一些功能,只有在布尔值(@myboolean
)为真时才选择额外的列:
ALTER PROCEDURE [dbo].[myProcedure]
--Parameters for the stored procedure
@myboolean as bit
AS
BEGIN
SET NOCOUNT ON;
SELECT
field1 AS first_field,
field2 AS second_field,
/* PROBLEM 1: select field3 and field4 only if @myboolean is true */
CASE
WHEN (@myboolean = 1)
THEN
field3 AS third_field,
field4 As fourth_field,
ELSE
/* do nothing, select nothing here */
END,
field5 AS fifth_field,
field6 AS sixth_field
WHERE ( ( field1.value = thisvalue
/* PROBLEM 2: add WHERE clause to check field2.status only if @myboolean is true
* Currently only works if @myboolean = 1. I know this should be really simple but
* I can't figure it out.
* Do I need to implement a CASE statement for when @myboolean = 0? See below */
AND ((@myboolean = 1) AND (field2.status = 2))
AND field1.type IN ( 1, 2 ) )
AND (( field1.type NOT IN ( 28, 32 )
OR ( field1.type IS NULL ) )) )
END
所以:
当@myboolean
为false时,应选择字段1,2,5和6 - 与原始代码一样
当@myboolean
为真时,应选择字段1-6并检查field2.status
我一直在寻找,我所能找到的只是WHERE CASE @this THEN 1 ELSE 0
的例子。如果布尔值为假,我无法找到如何不检查列值。
对于问题2,我还尝试实施CASE
声明,例如
AND field2.status =
CASE
WHEN (@myboolean = 1)
THEN 2 ELSE *
END
当然这会产生一个syntax error near '*'
,但我无法弄清楚应该如何做。
更新
只是提醒一下,问题非常简单。原始的SELECT语句庞大而复杂。实际上有几个布尔值在起作用。我想避免在if
中包装SELECT语句,因为它会很快成为混乱代码的混乱巨像。
更新 Problem 2 solved由@jpw提供(请参阅编辑回答)
答案 0 :(得分:1)
我只是偶然发现了这一点,同时寻找其他东西,如果这已经解决了,那么道歉。
以下是查看问题解决方案的另一种方法:
ALTER PROCEDURE [dbo].[myProcedure]
--Parameters for the stored procedure
@myboolean as bit
AS
BEGIN
SET NOCOUNT ON;
SELECT
field1 AS first_field,
field2 AS second_field,
field3 AS third_field,
field4 As fourth_field,
field5 AS fifth_field,
field6 AS sixth_field
WHERE ( ( field1.value = thisvalue
AND ((@myboolean = 1) AND (field2.status = 2))
AND field1.type IN ( 1, 2 ) )
AND (( field1.type NOT IN ( 28, 32 )
OR ( field1.type IS NULL ) )) )
UNION
SELECT
field1 AS first_field,
field2 AS second_field,
NULL AS third_field,
NULL As fourth_field,
field5 AS fifth_field,
field6 AS sixth_field
WHERE ( ( field1.value = thisvalue
AND ((@myboolean != 1) AND (field2.status = 2))
AND field1.type IN ( 1, 2 ) )
AND (( field1.type NOT IN ( 28, 32 )
OR ( field1.type IS NULL ) )) )
END
免责声明:我没有测试过这段代码,它是一个复制和粘贴工作,稍微调整一下,但我希望它能以一种新的方式给你一个新的方向,使用UNION并根据设置返回结果集参数。
答案 1 :(得分:0)
第一个问题的答案是,您无法动态选择要在查询中输出的列,但您必须更改逻辑"外部"使用流语句控件(if-else)或动态sql(使用根据所使用的变量选择的部分连接最终查询字符串)的查询。
如你所知,有很多变数很快就会失控,所以"最好的"解决方案可能是将大型语句分解为几个较小的部分,然后根据需要将它们粘合在一起。视图也可能是将代码重构为不太复杂的东西的工具。
要回答问题的第二部分,应该起作用的条件是:
AND ((@myboolean = 1 AND field2.status = 2) OR @myboolean = 0)
答案 2 :(得分:0)
我在这里有点深入,因为我之前没有使用CASE
,但我在W3Schools sql editor尝试了以下内容,它似乎可以解决问题:
SELECT CustomerId,
CASE WHEN customerId < 5 -- Problem 1, first field
THEN CustomerName
END as optCustomerName,
CASE WHEN customerId > 3 -- Problem 1, second field
THEN ContactName
END optContactName
FROM Customers
WHERE
CustomerId < 15
AND
CASE WHEN CustomerId < 5 -- Problem 2, a complete condition
THEN CustomerName like 'an%'
ELSE 1
END;
以下是有关我的代码的一些注释,以及您需要对代码进行的相应更改:
customerId < 5
代替@myboolean = 0
CASE
语句要替换SELECT
子句中的一个且只有一个列定义,因此您需要两个CASE
来包含field3
}和field4
CASE
列定义进行别名,因为它看起来很丑陋: - )SELECT
中的字段数应该是常量,因此默认行为是在不满足条件时添加null
值。如果不需要,我相信你需要使用另一个答案中建议的IF
语句的一些变体CASE
而不是where条件时,它看起来更好,并且如果你包围整个部分,然后在它不匹配时提供正确的默认值,则更容易阅读有了这些知识,我建议您对代码进行以下更改:
...
field2 AS second_field,
CASE WHEN (@myboolean = 1) THEN field3
END as third_Field,
CASE WHEN (@myboolean = 1) THEN field4
END as fourth_Field,
field5 AS fifth_field,
...
WHERE
...
AND
CASE
WHEN (@myboolean = 1) THEN field2.status = 2
ELSE 1 -- Always true, when not hitting the when @myboolean
END
AND
...
在这里和那里留下片段,特别是在WHERE
子句中,因为它看起来有点混乱所有的括号。但是你应该得到如何做出改变的概念。