как эффективно изменить предложение In в SQL - PullRequest
0 голосов
/ 08 мая 2018

у нас есть таблица employee_master и таблица 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 голосов
/ 08 мая 2018

Вы можете попробовать выполнить фильтрацию заранее:

(для вашего следующего вопроса: такой макет должен быть сделан вами)

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
0 голосов
/ 08 мая 2018

Вместо того, чтобы извлекать все значения и затем видеть, является ли ваше значение частью этого, вы должны фильтровать по вашему значению. Попробуйте, если это поможет (только один пример):

замена

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'
)

Теперь было бы также полезно включить столбец report_code в ИНДЕКС (надеюсь, вы используете ИНДЕКСЫ?)


Обновление - чтобы пропустить фильтрацию в случае '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
)
...