2012-05-04 7 views
22

He buscado y encontré esto SQL selecting rows by most recent date Que es lo más parecido a lo que quiero pero parece que no puedo hacer que funcione.
Aparece un error La 'ID' de columna no es válida en la lista de selección porque no está contenida ni en una función de agregado ni en la cláusula GROUP BY.SQL Seleccione los registros más nuevos que tienen una columna Nombre distinto

Quiero la fila más reciente según la fecha para cada nombre distinto

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

Aquí es un ejemplo de lo que quiero

  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 

resultado deseado

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

estoy usando Microsoft servidor sql 2008

Gracias por cualquier ayuda o puntos en la dirección correcta

Respuesta

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 

Aquí es una SQL Fiddle con una demo

o como señala Conrad se puede usar un 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

Mientras esto funciona, no puede crear un tie-breaker sin alguna concatenación de campo. Es por eso que normalmente uso una unión interna en su lugar [como esta] (http://sqlfiddle.com/#!3/e7382/7) cuando no estoy usando row_number() –

+1

@ConradFrix de acuerdo, esa fue la segunda versión que tuve voy a publicar, acabo de hacer esto primero. Editaré mi respuesta con la segunda opción también. Gracias por la sugerencia. – Taryn

+0

Fui con la primera parte de esto y funciona perceptivamente. El desempate no será una preocupación ya que en realidad estoy usando un horario, y las posibilidades de que coincidan dos fechas son menores que las posibilidades de ganar la lotería. Aprecio tu ayuda en esto chicos. –

13

Hay varias formas de hacerlo. Este usa ROW_NUMBER. Solo particione por Nombre y luego ordene por lo que quiere poner los valores que desea en la primera posición.

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

Nota probablemente debería añadir ID (partition BY NAME ORDER BY date DESC, ID DESC) en su consulta real como un juego de desempate de la fecha

+0

Esto se ve muy complicado, voy a dar una oportunidad y informar cómo funciona –

+0

No digo que este método no funcione, pero hay demasiadas preguntas sin respuesta para mí, no puedo acceder a la demostración (trabajo Internet ha bloqueado esa página) y en lugar de molestarlos con más What He intentado una de las otras respuestas que parece funcionar para mí. +1 upvote ya que no tengo dudas de que funciona –

+0

@ K'Leg ¿sabes por qué tu internet de trabajo está bloqueando sqlfiddle? Lo pregunto porque sqlfiddle.com es mi sitio (intentaré no tomarlo personalmente, je). –

0
select * from (
    Select 
     ID, Name, Price, Date, 
     Rank() over (partition by Name order by Date) RankOrder 
    From table 
) T 
where RankOrder = 1 
Cuestiones relacionadas