Как избежать вложенного подзапроса в SQL - PullRequest
0 голосов
/ 13 мая 2009

У меня есть таблица SQL, которая содержит данные вида:

Id int EventTime dateTime CurrentValue int

Таблица может иметь несколько строк для данного идентификатора, которые представляют изменения значения со временем (EventTime, идентифицирующий время, в которое значение изменилось).

Учитывая конкретный момент времени, я хотел бы иметь возможность рассчитать количество различных идентификаторов для каждого данного значения.

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

SELECT [Id],   
(  
    SELECT  
        TOP 1 [CurrentValue]  
    FROM [ValueHistory]  
    WHERE [Ids].[Id]=[ValueHistory].[Id] AND
        [EventTime] < @StartTime  
    ORDER BY [EventTime] DESC  
) as [LastValue]  
INTO #temp  
FROM [Ids]  

SELECT [LastValue], COUNT([LastValue])
FROM #temp  
GROUP BY [LastValue]  
DROP TABLE #temp

Ответы [ 3 ]

1 голос
/ 13 мая 2009

Мне кажется, я понимаю ваш вопрос.

Вы хотите получить самое последнее значение для каждого идентификатора, сгруппировать его по этому значению, а затем посмотреть, сколько идентификаторов имеют такое же значение? Это правильно?

Если так, вот мой первый выстрел:

declare @StartTime datetime
set @StartTime = '20090513'

select ValueHistory.CurrentValue, count(ValueHistory.id)
from
(
    select id, max(EventTime) as LatestUpdateTime
    from ValueHistory
    where EventTime < @StartTime
    group by id
) CurrentValues
inner join ValueHistory on CurrentValues.id = ValueHistory.id
and CurrentValues.LatestUpdateTime = ValueHistory.EventTime
group by ValueHistory.CurrentValue

Хотя нет гарантии, что это на самом деле быстрее - для работы с любой приличной скоростью вам понадобится индекс на EventTime.

1 голос
/ 13 мая 2009

Вот мой первый ход:

select ids.Id, count( distinct currentvalue)
from ids
join valuehistory vh on ids.id = vh.id
where vh.eventtime < @StartTime
group by ids.id

Однако я не уверен, что очень хорошо понимаю вашу модель стола или конкретный вопрос, который вы пытаетесь решить.

Это будет: отличные «текущие значения» от истории значений до определенной даты, которая для каждого идентификатора.

Это то, что вы ищете?

0 голосов
/ 13 мая 2009

Давайте помнить, что поскольку язык SQL описывает то, что вы хотите, а не то, как его получить, существует много способов выражения запроса, который в конечном итоге будет превращен в один и тот же план выполнения запроса хорошим оптимизатором запросов. Конечно, уровень «хорошо» зависит от базы данных, которую вы используете.

Как правило, подзапросы представляют собой синтаксически иной способ описания объединений. Оптимизатор запросов распознает это и определит наиболее оптимальный способ выполнения запроса. Временные таблицы могут быть созданы по мере необходимости. Поэтому во многих случаях повторная обработка запроса ничего не изменит для вашего фактического времени выполнения - в конечном итоге он может оказаться в том же плане выполнения запроса.

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

Теперь, после всего сказанного, вставленный вами запрос не полностью совместим с вашей заявленной целью «подсчета [количества] различных идентификаторов для каждого данного значения». Так что извините, если я не совсем отвечаю на ваши запросы, но вот что нужно протестировать против вашего текущего запроса. (Синтаксис приблизительный, извините - подальше от моего стола).

SELECT [IDs].[Id], vh1.[CurrentValue], COUNT(vh2.[CurrentValue]) FROM
    [IDs].[Id] as ids JOIN [ValueHistory] AS vh1 ON ids.[Id]=vh1.[Id]
        JOIN [ValueHistory] AS vh2 ON vh1.[CurrentValue]=vh2.[CurrentValue]
GROUP BY [Id], [LastValue];

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...