Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有更好的方法来编写这个gross SQL?_Sql_Sql Server_String_Query Optimization_Where Clause - Fatal编程技术网

有没有更好的方法来编写这个gross SQL?

有没有更好的方法来编写这个gross SQL?,sql,sql-server,string,query-optimization,where-clause,Sql,Sql Server,String,Query Optimization,Where Clause,因此,我正在为一个报表创建一个查询,该报表可能有几个可选的过滤器。我只在这里加入了客户端和站点,以保持简单。这些选项中的每一个都可以是包含或排除,并且可以包含NULL、1或多个值。因此,在将varchar连接到查询之前,我将其拆分为一个表 执行此测试大约需要15分钟,这。。。只是不行:p有更好的办法吗?我们使用动态sql编写了类似的查询,我试图避免这种情况,但可能没有办法解决这个问题 DECLARE @ClientsInc VARCHAR(10) = 'ABCD, EFGH', @Cli

因此,我正在为一个报表创建一个查询,该报表可能有几个可选的过滤器。我只在这里加入了客户端和站点,以保持简单。这些选项中的每一个都可以是包含或排除,并且可以包含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)
        )

首先,我总是倾向于在这种情况下提及

然而,您似乎已经意识到了两个选项:一个是动态SQL。另一个通常是老把戏
和(@var为null或@var=各自的_列)
。然而,这个技巧只适用于每个变量的一个值


您的解决方案似乎确实适用于多个值。但在我看来,您太过努力地避免使用动态sql。您的需求非常复杂,足以保证它。请记住,通常情况下,动态sql对您来说更难编写代码,但在复杂的情况下,对服务器来说更容易编写,而这一点肯定是正确的。猜测性能总是有风险的,但我想在这种情况下会有改进。

我会使用
存在
不存在

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\u split()
    ,而不是您似乎正在使用的自定义拆分器。它在SQL Server 2016及更高版本中可用,并返回一个名为
    value
    的列。如果您运行的是早期版本,则可以将其更改回客户功能

  • 根据我的理解,在使用
    exists
    之前,需要检查“include”参数是否为空,而“exclude”变量则不需要


当我执行include和excludes时,我会对include表使用
内部连接
,然后对exclude表使用
不存在的地方使用
子句。这听起来是否符合您的include/exclude逻辑?我考虑过这一点,但我认为它在这种情况下不起作用,因为如果include为NULL,那么我希望提取所有内容。例如,如果ClientInc为NULL,那么我需要所有的客户端,而不是一个客户端。你是对的,动态sql感觉非常粗糙和丑陋,但也许我应该更多地考虑什么是有意义的,而不是什么是最漂亮的:)我会接受这一点,因为它会起作用。谢谢你的轻推!