2010-10-21 2 views
2

У меня есть 2 таблицы, одна из которых содержит идентификаторы счетчика, а другая содержит измерения для некоторых метров в первой таблице. Это структура таблицы:Выберите последнее значение за месяц для всех заданных идентификаторов

MeterConfig:

  • MeterID (INT)
  • MeterNumber (символ [16])
  • Тип (символ [25])

чтения:

  • MeterID (int)
  • Дата (даты и время)
  • значение (числовой (18,6))

Мне нужно получить последнее чтение (и его дату) из заданного периода для каждого метра, а также номер счетчика , Мне удалось сделать это в T-SQL, хотя я не очень доволен тем, как я сделал это с помощью этого запроса:

select distinct 
cfg.MeterNumber, 
(select top 1 r.Date from Readings as r where r.Date between @startdate and @endDate and r.MeterID = cfg.MeterID order by r.Date desc) as Date, 
(select top 1 r.Value from Readings as r where r.Date between @startdate and @endDate and r.MeterID = cfg.MeterID order by r.Date desc) as Value 
from 
MeterConfig cfg, Readings r1 
where cfg.MeterID = r1.MeterID and r1.Date between @startdate and @endDate; 

Как я могу сделать это более эффективно?

ответ

4
WITH CTE AS (
SELECT mc.MeterID, Date, Value, ROW_NUMBER() OVER (PARTITION BY mc.MeterID ORDER BY Date DESC) as Rank 
FROM MeterConfig mc 
INNER JOIN Readings rd 
ON mc.MeterID = rd.MeterID 
WHERE rd.Date BETWEEN @startdate AND @endDate) 
SELECT * FROM CTE WHERE Rank = 1 
1

Предполагая, что даты в Чтения уникальны (ic включают временную метку), следующая должна быть эквивалентна вашему запросу.

SELECT DISTINCT cfg.MeterNumber 
     , r1.Date 
     , r1.Value   
FROM MeterConfig cfg 
     INNER JOIN Readings r1 ON cfg.MeterID = r1.MeterID 
     INNER JOIN (  
      SELECT date = MAX(r.Date) 
      FROM Readings r 
      WHERE r.Date BETWEEN @StartDate AND @EndDate 
     ) r2 On r2.date = r1.date   
+0

Спасибо, это кажется намного лучше. Однако одно изменение; первая часть должна быть 'SELECT DISTINCT cfg.MeterNumber, r1.Date, r1.Value'. ** r ** выходит за рамки. – alex

+0

@alex, thx, я обновил ответ. Если вы считаете, что это полностью отвечает на ваш вопрос, вы можете принять это как ответ. –

+0

@Lieven Я оставлю вопрос открытым еще на несколько часов, после чего, если это лучший ответ, я помету ваш ответ как принятый. Спасибо! – alex

Смежные вопросы