2014-01-30 6 views
0

я переменная, объявленная как этотT-SQL - условие, где производительность

DECLARE @Customer_No VARCHAR(MAX) 
SET @Customer_No = 'Z110073574;Z110027464;Z110229752;Z110274156;Z110170566;Z110102837;Z110074199' 

запрос содержит условию

WHERE ((@Customer_No = '') OR ([Customer No_] IN (SELECT [No_] FROM Customer))) 

Если переменная @Customer_No может содержит пустое значение (''), фильтрация должна пропустить. Если переменная содержит клиентов, разделенных точкой с запятой, строка анализируется в таблице Customer и запрос фильтруется значениями в таблице Customer.

Запрос занимает 15 минут. Если я использую только второе условие, это занимает около 50 секунд.

WHERE [Customer No_] IN (SELECT [No_] FROM Customer) 

Я не понимаю. Как это возможно? Любое решение? Объяснение? Спасибо.

Edit: Запрос

SELECT DET.[Cust_ Ledger Entry No_] 
     , DET.[Amount] 
     , DET.[Entry Type] 
     , CLE.[Document No_] 
FROM [dbo].[Company$Cust_ Ledger Entry] CLE 
LEFT JOIN [dbo].[Company$Detailed Cust_ Ledg_ Entry] DET ON CLE.[Entry No_] = DET.[Cust_ Ledger Entry No_] 
WHERE ((@Customer_No = '') OR (DET.[Customer No_] IN (SELECT [No_] FROM Customer))) 
    AND (DET.[Entry Type] = 1 OR DET.[Entry Type] = 2) 
    AND (CLE.[Due Date] >= @FromDueDate AND CLE.[Due Date] <= @ToDueDate) 
    AND CLE.[Posting Date] <= @ToDate 
+0

Является ли это хранимая процедура ?, сколько строк в вашей таблице ?. Можете ли вы показать планы выполнения? – Lamak

+7

Кроме того, кто называет ваши столбцы? Я хотел бы представить свои запястья своему правителю. –

+1

Вам действительно нужен VARCHAR (макс.) – Sparky

ответ

1

Я думаю, вы можете просто запрос без потери целостности в следующем. Как сказал Аарон, вы можете опубликовать план запроса?

SELECT 
    DET.[Cust_ Ledger Entry No_], 
    DET.[Amount], 
    DET.[Entry Type], 
    CLE.[Document No_] 
FROM 
    [dbo].[Company$Cust_ Ledger Entry] CLE 
LEFT JOIN 
    [dbo].[Company$Detailed Cust_ Ledg_ Entry] DET 
ON 
    CLE.[Entry No_] = DET.[Cust_ Ledger Entry No_] 
WHERE 
    (@FAS_No = '' OR DET.[Customer No_] IN (SELECT [No_] FROM Customer)) 
    AND DET.[Entry Type] in (1, 2) 
    AND CLE.[Due Date] >= @FromDueDate 
    AND CLE.[Due Date] <= @ToDueDate 
    AND CLE.[Posting Date] <= @ToDate 
+0

Variable @Customer_No принимает пользовательский ввод от SSRS. Пользователь может выбрать фильтр для конкретных клиентов или оставить его пустым (= создать отчет для всех клиентов). – Rutz

+0

Что {@FAS_No = ''} может быть использовано? что переменная @FAS не используется нигде в фильтрах, почему бы просто не избавиться от нее? – jean

+0

Извините. Переменная FAS_No на самом деле является моей переменной Customer_No. Я хотел сделать это более очевидным, это число клиентов. Собираюсь отредактировать вопрос. – Rutz

0

Непросто точно определить проблему без дополнительной информации (структура таблицы, количество строк и т. Д.). Однако, несомненно, использование OR в TSQL снижает общую производительность. Если есть способ использовать И вместо ИЛИ, чем рекомендуется, сделайте это.

то, что вы всегда можете сделать, использует оператор IF, который проверяет, является ли переменная пустой. Если нет, вы используете SELECT с WHERE. Если он пуст, вы используете SELECT без WHERE.

Еще одна вещь, которую можно проверить, может быть, ваши индексы. Это может немного ускорить работу.

+0

Да, я подумал об этом. Поскольку это SSRS, это может быть превращено в хранимую процедуру. –

0

DET в где же убивает влево так, возможно, также присоединиться к
Если потянуть условия в объединение оптимизатор запросов, кажется, делает лучше
Я думаю, что это дает оптимизатору в запросе больше шансов

SELECT DET.[Cust_ Ledger Entry No_] 
     , DET.[Amount] 
     , DET.[Entry Type] 
     , CLE.[Document No_] 
    FROM [dbo].[Company$Cust_ Ledger Entry] CLE 
    JOIN [dbo].[Company$Detailed Cust_ Ledg_ Entry] DET 
    ON CLE.[Entry No_] = DET.[Cust_ Ledger Entry No_] 
    AND (DET.[Entry Type] IN (1,2)) 
    AND (CLE.[Due Date] >= @FromDueDate AND CLE.[Due Date] <= @ToDueDate) 
    AND CLE.[Posting Date] <= @ToDate 
    JOIN Customer 
    ON @Customer_No = '' 
    OR DET.[Customer No_] = Customer.[No_] 

И пытаются намеки
Я хотел бы начать с ВНУТРЕННЕЙ MERGE JOIN Клиента

И пожалуйста [no_] объявлены как PK

0

Я думаю, что вы можете уменьшить производительность путем записи в

  • USE КТР для - (SELECT [No_] FROM Customer)
  • Регистрация КТР с основной таблицей, которая даст вам производительность
Смежные вопросы