我想在一个大的SQL查询中重用一个条件,这可能吗?

时间:2018-01-24 12:29:47

标签: sql sql-server ssms

例如,我需要重用这样的条件:

e.exampleTableDate between '2018-01-01' and '2018-01-10'

在文字的多个地方。是否可以在开始时将此查询放在某种占位符中,并更改它以便在任何地方更改它。

我想我可以随处更换文字,但此时我想知道这是否可能。在SQL中这个上下文中是否存在占位符和变量等内容?

附加示例:

select
   c.name,
   (
      select distinct id
      from x
        left join y
      where
        condition 1,
        condition 2,
        **repeating condition**
   ) [stuff 1],

   (
      select distinct id
      from x
        left join y
      where
        condition 1,
        condition 2,
        condition 3,
        **repeating condition**
   ) [stuff 2],

   (
      select distinct id
      from x
        left join y
      where
        condition 1,
        **repeating condition**
   ) [stuff 3]

from country c

order by c.name

2 个答案:

答案 0 :(得分:2)

也许你可以用视图做你想做的事情:

create view v_e as
    select e.*
    from e
    where e.exampleTableDate between '2018-01-01' and '2018-01-10';

您可以稍后在脚本中引用视图 - 或者在任何地方引用视图,因为视图是数据库的一部分。

e.g。请参阅下面的重用此查询的示例,同时还为每次使用添加其他(不同)条件:

select exampleTableId, exampleTableDate
from v_e x
where exampleTableCol in ('abc', 'def')
and not exists 
(
    select top 1 1
    from v_e y
    where y.ParentId = x.ParentId
    and y.exampleTableDate > x.exampleTableDate
)

除了视图,您可能会对公用表格表达式(CTEs)或Table Value Functions感兴趣,具体取决于具体情况。

答案 1 :(得分:1)

您可以使用动态SQL执行此操作...但是,这可能会让您对SQL注入攻击持开放态度,具体取决于用于构建重用字符串的值来自何处:

declare @reuseString nvarchar(max) = 'e.exampleTableDate between ''2018-01-01'' and ''2018-01-10'''
, @sql nvarchar(max)

set @sql = '
    select exampleTableId Id, exampleTableDate [Date]
    from myTable e
    where ' + @reuseString  + '
    union all
    select anotherTableId, anotherTableDate
    from myOtherTable e
    where ' + @reuseString  + '
'
exec (@sql)

set @sql = '
    select *
    from aCompletelyDifferentQuery e
    where ' + @reuseString  + '
    and xyz > 123
'
exec (@sql)

如果该可重用字符串可能为空(即在上面的示例中导致问题,因为那时会有and而没有前面的where,请更改代码,如下所示;无论是否填充了重用字符串。

declare @reuseString nvarchar(max) = 'and (e.exampleTableDate between ''2018-01-01'' and ''2018-01-10'')'
, @sql nvarchar(max)

--set @reuseString = '' --optional statement to illustrate the query working when this string's blank

set @sql = '
    select *
    from aCompletelyDifferentQuery e
    where (1=1) --ensure there's always a where, without influencing the query
    ' + @reuseString  + '
    and xyz > 123
'
exec (@sql)

如果您重复使用查询(即将同一过滤器应用于同一个表),则有更好的方法(视图,CTE或表值函数);有关详情,请参阅@GordonLinoff的答案。

如果您正在使用其他语言来调用SQL语句(例如,您已经编写了C#应用程序),那么这些语言中还有其他选项......因为您已经指定了SSMS但是,在你的问题标签中,我认为这不是你所追求的。