[英]SQL CASE in WHERE Clause using parameters
I have 4 date columns in my Date table, I want to write a query that will hit one of these columns depending on that user passes as a parameter: here is a part of my code: 我的Date表中有4个date列,我想编写一个查询,该查询将根据该用户作为参数传递到这些列之一:这是我的代码的一部分:
Select ...
FROM...
WHERE
CASE
WHEN @timePeriod = 'Cal' THEN d.CalendarYear = @year
WHEN @timePeriod = 'Fin' THEN d.FinancialYear = @year
WHEN @timePeriod = 'Mar' THEN d.YearEndedMarch = @year
WHEN @timePeriod = 'Sep' THEN d.YearEndedSep = @year
END
So the user will provide a TimePeriod, eg 'Fin' and the actual year 'FY2013 - 2014'. 因此,用户将提供一个TimePeriod,例如“ Fin”和实际年份“ FY2013-2014”。 Thus, if the user proivdes @timePeriod = 'Fin' I want the query to filter the Date table by @year. 因此,如果用户提供@timePeriod ='Fin',我希望查询按@year过滤Date表。
Here is a sample of what Im trying to get: I have some data in the Data column, and then I want the query to filter the results by one of these 4 calendar columns. 这是Im试图获得的示例:我在“数据”列中有一些数据,然后我希望查询通过这4个日历列之一来过滤结果。
You do do this without a CASE
statement and using simple logic: 您无需使用CASE
语句并使用简单的逻辑即可执行此操作:
Select ...
FROM...
WHERE
(@timePeriod = 'Cal' AND d.CalendarYear = @year)
OR (@timePeriod = 'Fin' AND d.FinancialYear = @year)
OR (@timePeriod = 'Mar' AND d.YearEndedMarch = @year)
OR (@timePeriod = 'Sep' AND d.YearEndedSep = @year)
[Given the cardinality for all these columns is very similar (or identical) you should not have to worry about parameter sniffing caching an inappropriate query plan.] [鉴于所有这些列的基数都非常相似(或相同),因此您不必担心参数嗅探会缓存不合适的查询计划。]
Yet another variation: 另一个变化:
Select ...
FROM...
WHERE @year =
CASE
WHEN @timePeriod = 'Cal' THEN d.CalendarYear
WHEN @timePeriod = 'Fin' THEN d.FinancialYear
WHEN @timePeriod = 'Mar' THEN d.YearEndedMarch
WHEN @timePeriod = 'Sep' THEN d.YearEndedSep
END
And this one, which may be faster than one using CASE
or OR
: 这可能比使用CASE
或OR
速度更快:
Select ...
FROM...
WHERE @timePeriod = 'Cal' and d.CalendarYear = @year
UNION ALL
Select ...
FROM ....
WHERE @timePeriod = 'Fin' and d.FinancialYear = @year
UNION ALL
... etc...
The idea behind this second one is that each SELECT
is very simple and can take advantage of any indexes you might have, while the UNION ALL
combines them without attempting to filter out duplicates. 第二个SELECT
背后的想法是,每个SELECT
非常简单,可以利用您可能拥有的任何索引,而UNION ALL
会将它们组合在一起,而不会尝试过滤出重复项。 Since @timePeriod can only have one value at a time, no records will be returned for 3 of the queries, and there'll be no duplicates to require removing. 由于@timePeriod一次只能有一个值,因此不会为3个查询返回任何记录,并且不会有重复项需要删除。
Use sub-query: 使用子查询:
Select ...
FROM
(
SELECT
CASE
WHEN @timePeriod = 'Cal' THEN d.CalendarYear
WHEN @timePeriod = 'Fin' THEN d.FinancialYear
WHEN @timePeriod = 'Mar' THEN d.YearEndedMarch
WHEN @timePeriod = 'Sep' THEN d.YearEndedSep
END as date
FROM...) t
WHERE t.date = @year
Hello we can make query more faster by using Union all with in the Subquery i am just giving syntax like example because there is no availability of data 您好,我们可以通过在子查询中使用Union All来使查询更快,因为没有数据,我只是给出像示例这样的语法
Select t.TimePeriod,t.CalendarYear
FROM
(
SELECT TIMEID,
@timePeriod = 'Cal' FROM @x where t.CalendarYear = @year
UNION ALL
SELECT TIMEID,
@timePeriod = 'FIN' FROM @x where t.CalendarYear = @year
UNION ALL
SELECT TIMEID,
@timePeriod = 'MAR' FROM @x where t.CalendarYear = @year
UNION ALL
SELECT TIMEID,
@timePeriod = 'Sep' FROM @x where t.CalendarYear = @year
) t
WHERE t.date = @year
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.