"Подзапрос имеет несколько строк для сравнения

У меня есть одна таблица, приведенная ниже.

В следующем запросе внешний запрос включается в like сравнение на tag столбец с подзапросом.

 SELECT top 6 *
  FROM [piarchive].[picomp2]
  WHERE tag Like
  (
  Select distinct left(tag,19) + '%' 
  from (SELECT  *
  FROM [piarchive].[picomp2]
  WHERE tag like '%CPU_Active' and  time between '2014/10/02 15:13:08'and'2014/10/02 15:18:37'
  and value=-524289 order by time desc) as t1
  )  
  and tag not like '%CPU_Active' and tag not like '%Program%' and time between '2014/10/02    
  15:13:08'and'2014/10/02 15:18:37'  order by time desc

Но этот подзапрос возвращает несколько строк, вызывая следующую ошибку:

Ошибка: "При использовании в качестве выражения подзапрос может возвращать не более одной строки".

1 ответ

Заменить where tag like (...) (где ... это подзапрос, опущенный здесь для краткости) расстаться с where exists (...)и принести like сравнение в подзапрос.


select top 6
    *
from
    [piarchive].[picomp2] t0
where
    exists
    (
        select
            *
        from
            (
                select
                    *
                from
                    [piarchive].[picomp2]
                where
                    tag like '%cpu_active' and time between '2014/10/02 15:13:08' and '2014/10/02 15:18:37'
                    and
                    value = -524289
            )
            as t1
        where
            t0.tag like left(t1.tag, 19) + '%' 
    ) 
    and
    tag not like '%cpu_active'
    and
    tag not like '%program%'
    and
    time between '2014/10/02 15:13:08' and '2014/10/02 15:18:37'
order by
    time desc;

Я добавил псевдоним таблицы во внешний запрос, чтобы устранить неоднозначность tag столбцы, но вы можете увидеть like сравнение смещено в подзапрос.

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

Подробнее об оптимизации

Это не будет легко оптимизировать, и индексы здесь будут бесполезны по следующим причинам:

  • Критерии объединения (t0.tag like left(t1.tag, 19) + '%') не является простым, и оптимизатору запросов может быть сложно создать что-то лучше, чем вложенные циклы (т. е. выполнить подзапрос для каждой строки внешнего запроса). Это, вероятно, ваш самый большой убийца производительности прямо здесь.
  • Ни один из like сравнения могут использовать табличные индексы, потому что они проверяют конец значения, а не начало.

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

select left(tag, 19) as key, *
  into #working
  from [piarchive].[picomp2]
 where [time] between '2014/10/02 15:13:08' and '2014/10/02 15:18:37';

#working теперь есть только записи за указанный период времени. Поскольку ваш примерный диапазон довольно узок (всего 5 с половиной минут), я бы поспорил, что это может выбить ~99% записей. Индекс на time значительно ускорит это. После того, как вы это сделаете, вы имеете дело только с крошечной частью данных.

Тогда, возможно (см. Позже) индекс key:

create clustered index cx_key on #working (key);

Затем выполните остальную часть запроса как:

select a.*
  from #working a
 where exists
       (
           select *
             from #working b
            where a.key = b.key and b.tag like '%cpu_active'
       )
       and
       a.tag not like '%program%'
       and
       a.tag not like '%cpu_active'

Я создал кластерный индекс по критериям объединения (первые 19 символов tag) оптимизировать подзапрос. Вам придется проверить это, так как это может не иметь никакого значения или даже замедлить процесс, если выигрыш перевесит стоимость создания индекса в первую очередь. Это будет зависеть от того, сколько данных у вас есть, и других факторов. Делая это, я получил только минимальный выигрыш (увеличение скорости примерно на 5%), хотя я использую только несколько сотен строк тестовых данных, которые я собрал. Чем больше у вас данных, тем эффективнее они должны быть.

Другие вопросы по тегам