2017-01-12 4 views
1

Может кто-то помочь мне оптимизировать этот запрос. Я написал только 2 из аргументов case, но на самом деле у них примерно 30 таких случаев, все вложенные, как показано в этом примере (с 2) ниже.TSQL Оптимизация для множественного вложенного запроса case

SELECT * 
FROM QS 
INNER JOIN R ON (CASE 
        WHEN R.FieldCode = 'L' 
         THEN --- 
       CASE 
        when (
        (R.Match = 1 AND QS.lineid 
        IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue))) 
        OR (R.Match = 0 AND QS.lineid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))) then 1 
        ELSE 0 
       END 
      ---- 
     WHEN R.FieldCode = 'D' 
      THEN 
       CASE 
        when ((R.Match = 1 AND QS.productid 
        IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue))) 
        OR (R.Match = 0 AND QS.productid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))) then 1 
        ELSE 0 
       END 
END)=1 
+0

Что является «неправильным» с запросом, который необходимо оптимизировать (низкая производительность, или просто утомительная и чрезвычайно длинная)? Возможно, лучше написать скалярную функцию, которая принимает FieldCode, Match, ProductId, FieldValue и т. Д., Поэтому логически логически логически логически входить в сумасшедший запрос (и его можно повторно использовать). –

+0

ЭТО СУПЕР МЕДЛЕННО КАК ISA – DinaDee

ответ

0

Это действительно плохой код SQL, так как двигатель базы данных не может делать какие-либо оптимизации вообще, так как она должна перечислить всю таблицу и идти запись по записи делает несколько тестов на каждом, в два раза.

Вы можете сделать это без каких-либо СЛУЧАЙ вообще:

SELECT * 
FROM QS 
INNER JOIN R ON ( (R.FieldCode = 'L' 
        AND ( (R.Match = 1 AND QS.lineid IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue))) 
          OR (R.Match = 0 AND QS.lineid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue))))) 
       OR (R.FieldCode = 'D' 
        AND ( (R.Match = 1 AND QS.productid IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue))) 
          OR (R.Match = 0 AND QS.productid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))))     
       ) 
+0

Вы говорите, что OR является лучше, чем заявление Case? Из того, что я вижу, это то, что вы здесь изменили. – DinaDee

+0

Процесс, используемый движком для обработки соединения, отличается. Вы можете увидеть разницу, если посмотреть на план выполнения запросов в SSMS. –

0

ли это работать лучше для вас? Не зная относительных строк или базовых данных, я бы подумал, что это может быть намного быстрее и проще в обслуживании, так как вам не нужно запускать скалярную функцию снова и снова, и она должна быть более оптимизированной.

SELECT * -- Change to only get fields you need from QS.* 
FROM (
    SELECT 
     QS.*, 
     ',' + CONVERT(VARCHAR(10), 
      CASE R.FieldCode 
       WHEN 'L' THEN QA.lineid 
       WHEN 'D' THEN QA.productid 
       -- ... 
       END + ',' AS MatchValue, 
     ',' + R.FieldValue + ',' AS FieldValueCSV 
     R.Match 
    FROM QS 
     CROSS JOIN R 
    ) T 
WHERE (T.Match = 1 AND T.FieldValueCSV LIKE '%' + T.MatchValue + '%') 
    OR (T.Match = 0 AND NOT T.FieldValueCSV LIKE '%' + T.MatchValue + '%') 
Смежные вопросы