如何有效地改变SQL

时间:2018-05-08 07:08:28

标签: sql-server tsql sql-server-2014 where-clause

我们有一个employee_master表和一个Report_Filter表,Report_Filter包含用户输入的不同类型的过滤器,例如。状态,员工代码,国家/地区等,此report_filter也包含用户信息。表结构就像这个Report_Filter(User_Id,Report_TYpe,Report_Code)都是字符字段。根据用户输入,表格将具有类似

的值
( 'User_1', 'STATUS', '01' ) 
( 'user_1', 'STATUS', '02'  ) 
( 'User_1', 'EMP_CODE', 'ABC' ) 
( 'User_1', 'NATIONALITY', 'ALL' ) -- All means he want to see all the nationalities

现在我们正在编写像这样的查询

Select Emp_code, Emp_Name, status, nationlity 

From  Empolyee_Master m
Where 

('All' in ( select report_code from Report_Filter where user_id = @user_id and report_type='STATUS') or m.STATUS in ( select report_code from Report_Filter where user_id = @user_id and report_type='STATUS') )    and  

or m.CATEGORY in ( select report_code from Report_Filter where user_id = @user_id and report_type='NATIONALITY') )               and  

or m.emp_code in ( select report_code from Report_Filter where user_id = @user_id and report_type='EMP_CODE') )

还有其他条件我们正在使用,问题是因为In子句需要花费太多时间。我们如何才能有效地更改此代码以提高性能

我们正在使用MSSQL 2014

2 个答案:

答案 0 :(得分:1)

您应该按值过滤,而不是检索所有值,然后查看您的值是否属于它的一部分。试试这是否有帮助(只是一个例子):

替换

WHERE 'ALL' in (
    select report_code from Report_Filter
    where user_id = @user_id and report_type='STATUS'
)

WHERE EXISTS (
    select 1 from Report_Filter
    where user_id = @user_id and report_type='STATUS'
    and   report_code = 'ALL'
)

现在,在INDEX中包含列report_code也会有所帮助(我希望你使用INDEX?)

更新 - 如果是' ALL'则跳过过滤,可以这样做:

DECLARE @statusFilter VARCHAR(20) = ...  -- 'ALL' or other value

SELECT ...
WHERE @statusFilter = 'ALL'
OR EXISTS (
    select 1 from Report_Filter
    where user_id = @user_id and report_type='STATUS'
    and   report_code = @statusFilter
)

答案 1 :(得分:0)

您可以提前尝试进行过滤:

(对于你的下一个问题:这样的模型应该由你完成)

DECLARE @ReportFilter TABLE([user_id] VARCHAR(100),report_type VARCHAR(100),report_code VARCHAR(100));
INSERT INTO @ReportFilter VALUES
 ( 'User_1', 'STATUS', '01' ) 
,( 'user_1', 'STATUS', '02'  ) 
,( 'User_1', 'EMP_CODE', 'ABC' ) 
,( 'User_1', 'NATIONALITY', 'ALL' );

DECLARE @Employee_Master TABLE(Emp_Code VARCHAR(100),Emp_Name VARCHAR(100), [status] VARCHAR(100), nationality VARCHAR(100));
INSERT INTO @Employee_Master VALUES
 ('ABC','test1','01','USA')
,('DEF','test2','99','GB')
,('ABC','test3','02','DE')
,('XYZ','test4','01','FRA');

- 这是您的查询的一部分

DECLARE @user_id VARCHAR(100)='User_1';

WITH filterSTATUS AS
(
    SELECT * FROM @ReportFilter WHERE [user_id]=@user_id AND report_type='STATUS'
    AND NOT EXISTS(SELECT 1 FROM @ReportFilter WHERE [user_id]=@user_id AND report_type='STATUS' AND report_code='ALL')
)
,
filterEMPCODE AS
(
    SELECT * FROM @ReportFilter WHERE [user_id]=@user_id AND report_type='EMP_CODE'
    AND NOT EXISTS(SELECT 1 FROM @ReportFilter WHERE [user_id]=@user_id AND report_type='EMP_CODE' AND report_code='ALL')
)
,filterNATIONALITY AS
(
    SELECT * FROM @ReportFilter WHERE [user_id]=@user_id AND report_type='NATIONALITY'
    AND NOT EXISTS(SELECT 1 FROM @ReportFilter WHERE [user_id]=@user_id AND report_type='NATIONALITY' AND report_code='ALL')
)
SELECT * 
FROM @Employee_Master AS em
WHERE (SELECT COUNT(*) FROM filterSTATUS)=0 OR em.[status] IN (SELECT x.report_code FROM filterSTATUS AS x)
  AND (SELECT COUNT(*) FROM filterEMPCODE)=0 OR em.Emp_Code IN (SELECT x.report_code FROM filterEMPCODE AS x)
  AND (SELECT COUNT(*) FROM filterNATIONALITY)=0 OR em.nationality IN (SELECT x.report_code FROM filterNATIONALITY AS x);

对于给定集,这将返回

Emp_Code    Emp_Name    status  nationality
ABC         test1       01      USA
ABC         test3       02      DE