有没有更好的方法来编写此总SQL?

时间:2020-07-23 21:17:44

标签: sql sql-server string query-optimization where-clause

因此,我正在为一个可能有多个可选过滤器的报告创建查询。为了简化起见,我仅在此处包括了客户端和站点。这些选项中的每一个都可以是包含或排除,并且可以包含NULL,1或多个值。因此,在将varchar加入查询之前,我将其拆分为一个表。

该测试大约需要15分钟的时间来执行,而...:p不会这样做:有没有更好的方法?我们有使用动态sql编写的类似查询,但我试图避免这种情况,但也许对此没有办法?

DECLARE   
@ClientsInc VARCHAR(10) = 'ABCD, EFGH', 
@ClientsExc VARCHAR(10) = NULL,     
@StationsInc VARCHAR(10) = NULL, 
@StationsExc VARCHAR(10) = 'SomeStation'
    
SELECT *
INTO #ClientsInc
FROM dbo.StringSplit(@ClientsInc, ',')
SELECT *
INTO #ClientsExc
FROM dbo.StringSplit(@ClientsExc, ',')
  
SELECT *
INTO #StationsInc
FROM dbo.StringSplit(@StationsInc, ',')
SELECT *
INTO #StationsExc
FROM dbo.StringSplit(@StationsExc, ',')    

SELECT [some stuff]
FROM media_order mo
LEFT JOIN #ClientsInc cInc WITH(NOLOCK) ON cInc.Value = mo.client_code
LEFT JOIN #ClientsExc cExc WITH(NOLOCK) ON cExc.Value = mo.client_code
LEFT JOIN #StationsInc sInc WITH(NOLOCK) ON sInc.Value = mo.station_name
LEFT JOIN #StationsExc sExc WITH(NOLOCK) ON sExc.Value = mo.station_name
WHERE ((@ClientsInc IS NOT NULL AND cInc.Value IS NOT NULL)
         OR (@ClientsExc IS NOT NULL AND cExc.Value IS NULL)
       )    
   AND ((@StationsInc IS NOT NULL AND sInc.Value IS NOT NULL)
         OR (@StationsExc IS NOT NULL AND sExc.Value IS NULL)
        )

2 个答案:

答案 0 :(得分:1)

首先,在这种情况下,我总是会提到Erland Sommarskog's Dynamic Search Conditions

但是,您似乎已经意识到两种选择:一种是动态SQL。另一个通常是古老的把戏and (@var is null or @var=respective_column)。但是,此技巧仅适用于每个变量一个值。

您的解决方案似乎确实适用于多个值。但是我认为,您正在努力避免动态sql。您的要求足够复杂,无法保证。并且请记住,通常,动态sql较难编写代码,但在复杂情况下对服务器而言则更容易-当然这是。猜测性能总是有风险的,但是我想在这种情况下会有改进。

答案 1 :(得分:0)

我将使用existsnot exists

select ...
from media_order mo
where
    (
        @ClientsInc is null
        or exists (
            select 1 
            from string_split(@ClientsInc, ',')
            where value = mo.client_code
        )
    )
    and not exist (
        select 1 
        from string_split(@ClientsExc, ',')
        where value = mo.client_code
    )
    and (
        @StationsInc is null
        or exists (
            select 1 
            from string_split(@StationsInc, ',')
            where value = mo.station_name
        )
    )
    and not exist (
        select 1 
        from string_split(@StationsExc, ',')
        where value = mo.station_name
    )

注意:

  • 我使用了内置函数string_split(),而不是您似乎正在使用的自定义拆分器。它在SQL Server 2016及更高版本中可用,并返回称为value的单个列。如果您运行的是早期版本,则可以将其更改回客户功能

  • 据我所知,您需要使用exists来检查“ include”参数是否为空,而不必“排除”变量

相关问题