SQL obteniendo el último elemento por fecha

I have a query that I had working on one item, then I wiped the dataset and started over and now I can't get it to pull any data at all.
La consulta es básicamente:

SELECT * 
FROM   TABLEA 
       LEFT JOIN TABLEB 
              ON TABLEA.ID = TABLEB.ID 
WHERE  TABLEA.ID = 1 
       AND TABLEB.DATE = (SELECT MAX(TABLEB.DATE) 
                          FROM   TABLEB 
                          WHERE  TABLEA.ID = 1) 

TableB tracks changes and has hundreds of entries per ID. I want a single row of the last chronological item pertaining to that ID.
If there is a better way to do this then awesome but I'd really like to know why this specific query isn't working. When I run this query:

SELECT MAX(TABLEB.DATE) 
FROM   TABLEB 
       LEFT JOIN TABLEB 
              ON TABLEA.ID = TABLEB.ID 
WHERE  TABLEA.ID = 1 

I get the proper value of the last date in the dataset.

preguntado el 09 de septiembre de 13 a las 21:09

Are you using SQL Server, PostgreSQL, MySQL? -

Go with CTE. Pretty much all latest versions of DB engines can handle this, except for MySQL. -

2 Respuestas

select * 
from tableA as a
    left outer join tableB as b on b.ID = a.ID
where
    b.Date = (select max(t.Date) from tableB as t WHERE t.ID = a.id)
    -- and a.ID = 1 if you need it

if you just need date from tableB, you can do

select * 
from tableA as a
    left outer join (
        select max(t.Date) as Date, t.ID from tableB as t group by t.ID
    ) as b on b.ID = a.ID
-- where a.ID = 1 if you need it

si puedes usar row_number function (you can change common table expression to subquery):

with cte as (
    select *, row_number() over(partition by a.ID order by b.Date desc) as rn
    from tableA as a
        left outer join tableB as b on b.ID = a.ID        
    -- where a.ID = 1 if you need it
)
select *
from cte
where rn = 1

if you're using SQL Server version >= 2005:

select * 
from tableA as a
    outer apply (
        select top 1 t.*
        from tableB as t
        where t.ID = a.ID
        order by t.Date desc
    ) as b
-- where a.ID = 1 if you need it

Please note using aliases in all subqueries.

About your initial query, I think you has an typo there:

SELECT * 
FROM   TABLEA 
       LEFT JOIN TABLEB 
              ON TABLEA.ID = TABLEB.ID 
WHERE  TABLEA.ID = 1 
       AND TABLEB.DATE = (SELECT MAX(TABLEB.DATE) 
                          FROM   TABLEB 
                          WHERE  TABLEA.ID = 1) -- <-- Do you mean TABLEB.ID = 1 ??

Respondido el 09 de Septiembre de 13 a las 22:09

This is amazing. Thank you so much. The first answer worked perfectly. Now I just have to research why it worked and buy an SQL book. - Keith

@Keith what RDBMS do you using? SQL Server? - Pekar romano

He aquí una forma:

SELECT *
FROM tableA LEFT JOIN
     tableB
     ON tableA.ID = tableB.ID
WHERE tableA.ID = 1
ORDER BY tableB.Date desc
LIMIT 1;

Respondido el 09 de Septiembre de 13 a las 22:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.