简体   繁体   English

使用参数的WHERE子句中的SQL CASE

[英]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 : 这可能比使用CASEOR速度更快:

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM