我有这个查询(伪代码)
SELECT
a = 1,
b = 2,
c = CASE
WHEN ISNULL(
(SELECT MONTH(GETDATE()) <---long query
), 0) = 0 THEN 'found'
ELSE
SELECT MONTH(GETDATE()) <--- repeated long query
END
问题在于SELECT MONTH(GETDATE())
实际上是非常长的查询。
这个“长表达式”是否有任何解决方法不会在查询中出现两次?
P.S。
我有一个将SELECT MONTH(GETDATE())
计算到外部变量的解决方案......但我想弄清楚是否有内联解决方案。
答案 0 :(得分:5)
您有多种选择:
根据数据的处理方式,确定最适合的数据。你的问题没有提供足够的细节来明确提出建议,但这些值得关注。
小心使用UDF,因为它们会迅速阻碍性能。我的经验法则是为简单的数据转换或数学计算编写UDF。我试图避免在函数中进行复杂的基于集合的操作,并且更喜欢视图或CTE。
答案 1 :(得分:2)
您的示例中子查询的特定使用模式可以像这样重写:
…
c = COALESCE(CAST(NULLIF((subquery), 0) AS varchar(10)), 'found')
…
正如Mikael Eriksson在他的评论中正确指出的那样,你可能需要在这里使用ISNULL
而不是COALESCE
,因为其中一个参数包含子查询而ISNULL
可能(或者事实上,在这种情况下会更有效率,正如你在this answer中所阐述的那样。
所以这是固定的ver:
…
c = ISNULL(CAST(NULLIF((subquery), 0) AS varchar(10)), 'found')
…
但请注意,如果您最终切换到ISNULL
,则应该注意第二个字符串('found'
)的长度,如果您决定更改它的话。问题是,ISNULL
将(尝试)将第二个参数强制转换为第一个参数的确切类型,包括指定字符串的最大长度(在本例中为10
)。如果您的第二个参数变为'NULL or zero is found'
而不仅仅是'found'
,ISNULL
将不会返回整个字符串,而只返回前10个字符('NULL or ze'
)。因此,您还需要记住更改第一个参数的类型(例如,更改为varchar(20)
)。
答案 2 :(得分:1)
SELECT
a = 1,
b = 2,
c = CASE
WHEN ISNULL([l], 0) = 0 THEN 'found'
ELSE [l]
END
from tbl
cross apply (
SELECT MONTH(GETDATE()) as [l]
) as [x]
此外,如果您的原始查询代表您实际获得的内容(即,如果“long expression”返回null,则返回一个值),请考虑使用COALESCE
而不是case语句。或者只使用ISNULL([l], 'found')
答案 3 :(得分:-1)
使用CTE的示例
;WITH CTE AS
(
SELECT CASE WHEN ISNULL(MONTH(GETDATE()),0) = 0
THEN 'FOUND' ELSE ISNULL(MONTH(GETDATE()),0) END Col1
),
SELECT a = 1,b = 2, C = col1
FROM Table1, CTE
如果您有任何密钥,可用于加入
SELECT a = 1,b = 2, C = CASE WHEN ISNULL(v.col1,0) = 0 THEN 'Found' ELSE v.col1 END
FROM Table1 a
OUTER APPLY (SELECT ISNULL(MONTH(DateCol),0) Col1 FROM TABLEName b
a.id = b.id) v