2014-10-27 5 views
1

Я пытаюсь выбрать самую последнюю ненулевую запись из моего набора данных в SQL. Большинство примеров этого удовлетворены возвратом только даты и группы по переменным, но я также хотел бы вернуть соответствующее значение. Например:Выберите самую последнюю запись в SQL

ID  Date   Value 
---------------------------- 
001  2014-10-01  32 
001  2014-10-05  10 
001  2014-10-17  0 
002  2014-10-03  17 
002  2014-10-20  60 
003  2014-09-30  90 
003  2014-10-10  7 
004  2014-10-06 150 
005  2014-10-17  0 
005  2014-10-18  9 

Использование

SELECT ID, MAX(Date) AS MDate FROM Table WHERE Value > 0 GROUP BY ID 

Возвраты:

ID  Date  
------------------- 
001  2014-10-05 
002  2014-10-20 
003  2014-10-10 
004  2014-10-06 
005  2014-10-18 

Но всякий раз, когда я пытаюсь включить значение в качестве одного из выбранных переменных, приводит SQLServer к ошибке:

"Column 'Value' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."

My des IRED результат будет:

ID  Date   Value 
---------------------------- 
001  2014-10-05  10 
002  2014-10-20  60 
003  2014-10-10  7 
004  2014-10-06 150 
005  2014-10-18  9 

Одно из решений я подумал бы посмотреть результаты обратно в исходной таблице и возвращает значение, которое соответствует соответствующему ID & Дата (я уже урезана и так Я знаю, что они уникальны), но это кажется мне бесполезным решением. Любая помощь по этому поводу будет оценена по достоинству.

ПРИМЕЧАНИЕ. Я не хочу группировать по значению, так как это результат, который я пытаюсь вытащить в конце (т. Е. Для каждого идентификатора я хочу последнее значение). Дальнейший пример:

ID  Date   Value 
---------------------------- 
001  2014-10-05  10 
001  2014-10-06  10 
001  2014-10-10  10 
001  2014-10-12  8 
001  2014-10-18  0 

Здесь я хочу только получить последнюю ненулевую запись. (001, 2014-10-12, 8)

SELECT ID, MAX(Date) AS MDate, Value FROM Table WHERE Value > 0 GROUP BY ID, Value 

вернуться бы:

ID  Date   Value 
---------------------------- 
001  2014-10-10  10 
001  2014-10-12  8 
+0

All эти самозапуска и т. д. могут быть улучшены с помощью оконных функций. [Пример SQLfiddle] (http://sqlfiddle.com/#!3/afe17/1). –

+0

@AaronBertrand, спасибо. Я уже внедрил код повторной ссылки ниже, прежде чем я прочитал это предложение, но я буду иметь это в виду, если мне когда-либо понадобится перекодировать в будущем. –

ответ

1

Предполагая, что вы не повторяющиеся даты для того же ID в таблице, это должно работать:

SELECT A.ID, A.Date, A.Value 
FROM 
    T1 AS A 
    INNER JOIN (SELECT ID,MAX(Date) AS Date FROM T1 WHERE Value > 0 GROUP BY ID) AS B 
     ON A.ID = B.ID AND A.Date = B.Date 
+0

Спасибо. Похоже, он должен работать. Если это самое простое решение моей проблемы, то, наверное, мне придется это сделать. Я просто подумал, что может быть что-то намного проще, чем повторная ссылка на мои исходные данные, подобные этому. –

+0

@ Michael существует гораздо лучшее решение с использованием оконных функций. –

+0

+1 для ответного редактирования и рабочего ответа. Добро пожаловать в Stack Overflow, @JoaoAraujo! – AHiggins

1
select a.id, a.date, a.value from Table1 a inner join (

select id, max(date) mydate from table1 
where Value>0 group by ID) b on a.ID=b.ID and a.Date=b.mydate 
+0

Спасибо за хороший ответ !!! – Ahmad

0

Использование Subqry,

SELECT ID, Date AS MDate, VALUE 
FROM table t1 
where date = (Select max(date) 
       from table t2 
       where Value >0 
       and  t1.id = t2.id 
       ) 
0

ответы, предоставленные вполне достаточно, но с помощью КТР:

;WITH cteTable 
AS 
(
    SELECT 
    Table.ID [ID], MAX(Date) [MaxDate] 
    FROM 
    Table 
    WHERE 
    Table.Value > 0 
    GROUP BY 
    Table.ID 
) 

SELECT 
    cteTable.ID, cteTable.Date, Table.Value 
FROM 
    Table INNER JOIN cteTable ON (Table.ID = cteTable.ID) 
2

Это также может быть сделано с помощью оконной функции, которая очень Ofter быстрее, чем объединение по сгруппированных запросу:

select id, date, value 
from (
    select id, 
     date, 
     value, 
     row_number() over (partition by id order by date desc) as rn 
    from the_table 
) t 
where rn = 1 
order by id; 
Смежные вопросы