Как оптимизировать SQL-запрос с помощью подзапроса? - PullRequest
0 голосов
/ 07 октября 2019

Я хочу улучшить производительность SQL-запроса. У меня есть таблица 'tblEntries' со столбцом 'sTag':

+----+------+-------+------+---------+
| Id | sTag | sPath | lVer | bActive |
+====+======+=======+======+=========+
| 1  | NULL |  t1   | 100  |   +     |
| 2  | NULL |  t2   | 110  |   +     |
| 3  | x1   |  t4   | 110  |   +     |
| 4  | x1   |  t3   | 120  |   +     |
| 5  | x2   |  t7   | 100  |   +     |
+----+------+-------+------+---------+

Клиент запрашивает путь с указанным тегом, и запрос должен вернуть указанную запись со следующим условием:

  1. Если есть запись с указанным тегом, она должна вернуть запись с максимальным значением lVer, а bActive должно быть ИСТИНА.
  2. Если нет записи с указанным тегом, он должен возвратить запись со значением NULL sTag и с максимальным значением lVer, а bActive должно быть ИСТИНА.

«С меткой»запись имеет больший приоритет над «без тега».

Текущий запрос SQL:

SELECT lVer, sPath 
FROM tblEntries 
INNER JOIN 
(SELECT MAX(lVer) AS V, sTag AS T 
FROM tblEntries 
WHERE bActive = TRUE 
GROUP BY sTag)
ON lVer = V 
WHERE T IS NULL OR T = 'user_tag' 
ORDER BY T DESC

Затем я могу выбрать первую запись, которая удовлетворяет условиям. Могу ли я избежать подзапроса?

Спасибо!

1 Ответ

0 голосов
/ 07 октября 2019

В зависимости от ваших данных и базы данных, это может иметь достаточную производительность:

select top (1) e.*
from tblEntries e
where e.bActive = TRUE and
      (e.t IS NULL OR e.t = 'user_tag')
order by (e.t desc),  -- null values last
         t.lver desc;

Если скорость действительно является проблемой, и у вас есть индекс на (t, active, lver desc), это может быть немного быстрее:

(select top (1) e.*
 from tblEntries e
 where e.t = 'user_tag' and e.bActive = TRUE 
 order by e.lver desc
) union all
(select top (1) e.*
 from tblEntries e
 where e.t is null and e.bActive = TRUE and
       not exists (select 1 from tblEntries e2 where e2.t = 'user_tag' and e2.bActive = TRUE )
 order by e.lver desc
);
...