2012-05-04 4 views
22

Я искал вокруг, и я нашел это SQL selecting rows by most recent date Это настолько близко к тому, что я хочу, но я не могу заставить его работать.
Я получаю сообщение об ошибке «Идентификатор столбца» недопустим в списке выбора, потому что он не содержится ни в агрегатной функции, ни в предложении GROUP BY.SQL Выберите самые новые записи, которые имеют отчетливый столбец Имя

Я хочу новейшую строку по дате для каждого отдельного имени

Select ID,Name,Price,Date 
From table 
Group By Name 
Order By Date ASC 

Вот пример того, что я хочу

  Table 
ID| Name | Price | Date 
--------------------------------- 
0 | A | 10 | 2012-05-03 
1 | B | 9 | 2012-05-02 
2 | A | 8 | 2012-05-04 
3 | C | 10 | 2012-05-03 
4 | B | 8 | 2012-05-01 

желаемого результата

ID| Name | Price | Date 
------------------------------ 
2 | A | 8 | 2012-05-04 
3 | C | 10 | 2012-05-03  
1 | B | 9 | 2012-05-02 

Я использую Microsoft sql server 2008

Спасибо за любую помощь или пункты в правильном направлении

ответ

41
Select ID,Name, Price,Date 
From temp t1 
where date = (select max(date) from temp where t1.name =temp.name) 
order by date desc 

Вот SQL Fiddle с демо

или как Конрад указывает, вы можете использовать INNER JOIN:

SELECT t1.ID, t1.Name, t1.Price, t1.Date 
FROM temp t1 
INNER JOIN 
(
    SELECT Max(date) date, name 
    FROM temp 
    GROUP BY name 
) AS t2 
    ON t1.name = t2.name 
    AND t1.date = t2.date 
ORDER BY date DESC 
+2

Пока это работает, вы не можете создать тай-брейк без какой-либо конкатенации полей. Вот почему я обычно использую внутреннее соединение вместо этого [http://sqlfiddle.com/#!3/e7382/7), когда не использовал row_number() –

+1

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

+0

Я пошел с первой частью этого, и это работает замечательно. Tie breaker не будет проблемой, поскольку я фактически использую datetime, и шансы на совпадение двух дат меньше, чем шансы на то, что я выиграю лотерею. Я ценю вашу помощь этим парням. –

13

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

WITH cte 
    AS (SELECT Row_number() OVER (partition BY NAME ORDER BY date DESC) RN, 
       id, 
       name, 
       price, 
       date 
     FROM table1) 
SELECT id, 
     name, 
     price, 
     date 
FROM cte 
WHERE rn = 1 

DEMO

Примечание Вы, вероятно, следует добавить идентификатор (partition BY NAME ORDER BY date DESC, ID DESC) в Вашем запросе в качестве галстука выключателя на дату

+0

Это выглядит очень сложным, я дам идти и сообщите мне, как это работает –

+0

Я не говорю, что этот метод не работает, но есть слишком много вопросов, не ответивших на меня, я не могу получить доступ к демонстрации (работа в Интернете заблокировала эту страницу), и вместо того, чтобы беспокоить вас, ребята с большим количеством дие я попробовал один из других ответов, которые, похоже, работают на меня. +1 upvote, так как я не сомневаюсь, что это работает –

+0

@ K'Leg вы знаете, почему ваша работа в Интернете блокирует sqlfiddle? Я спрашиваю, потому что sqlfiddle.com - мой сайт (я постараюсь не воспринимать это слишком лично, хех). –

0
select * from (
    Select 
     ID, Name, Price, Date, 
     Rank() over (partition by Name order by Date) RankOrder 
    From table 
) T 
where RankOrder = 1 
Смежные вопросы