如何使SQL JOIN只返回最近状态代码的一行?

时间:2013-01-09 20:38:55

标签: sql sqlite

以下SQL语句:

SELECT f.id, 
       f.front, 
       f.back, 
       h.statusChangedIdCode, 
       h.whenCreated,
       h.historyIdCode 
FROM dpod_site_flashcards AS f 
   JOIN dpod_site_historyItems AS h ON f.id = h.itemId 
WHERE f.id = 216 
  AND historyIdCode = 'statusChanged' 
ORDER BY h.whenCreated

给我以下输出。 如何更改它以便它只返回一行具有最新statusChangedIdCode?

enter image description here

4 个答案:

答案 0 :(得分:5)

SELECT f.id, 
       f.front, 
       f.back, 
       h.statusChangedIdCode, 
       h.whenCreated,
       h.historyIdCode 
FROM dpod_site_flashcards AS f 
   JOIN dpod_site_historyItems AS h ON f.id = h.itemId 
WHERE f.id = 216 
  AND h.historyIdCode = 'statusChanged' 
  AND h.whenCreated = (select max(whenCreated)
                       from dpod_site_historyItems h2
                       where h2.itemId = h.itemId
                         and h2.historyIdCode = 'statusChanged')
ORDER BY h.whenCreated

或者如果您有支持窗口函数的现代DBMS:

SELECT f.id, 
       f.front, 
       f.back, 
       h.statusChangedIdCode, 
       h.whenCreated,
       h.historyIdCode 
FROM dpod_site_flashcards AS f 
   JOIN (
     select itemid, 
            historyIdCode,
            whenCreated,
            statusChangedIdCode,
            row_number() over (partition by itemid order by whenCreated desc) as rn 
     from dpod_site_historyItems 
     where historyIdCode = 'statusChanged' 
   ) h ON f.id = h.itemId AND h.rn = 1
WHERE f.id = 216 
ORDER BY h.whenCreated

当您选择LIMIT解决方案不会执行的多个dpod_site_flashcards.id的行时,这两种情况都会起作用。

答案 1 :(得分:2)

试过这个?

SELECT f.id, f.front, f.back, h.statusChangedIdCode, MAX(h.whenCreated), h.historyIdCode 
FROM dpod_site_flashcards AS f 
JOIN dpod_site_historyItems AS h ON f.id=h.itemId 
WHERE f.id = 216 AND historyIdCode='statusChanged' 
GROUP BY f.id, f.front, f.back, h.statusChangedIdCode, h.historyIdCode 

-EDIT

哎呀,谢谢@Gordon,没有仔细阅读要求。这是一些应该完成工作的SQLFiddle

这是正确代码的代码片段 - 在WHERE子句中包含它:

h.whenCreated = (select max(whenCreated)
   from dpod_site_historyItems h2
   where h2.itemId = h.itemId)

答案 2 :(得分:1)

如果您使用MySQL,请将结尾更改为:ORDER BY h.whenCreated DESC LIMIT 1

答案 3 :(得分:1)

这是基于@ itchy的答案。最佳答案取决于数据库。

有些数据库支持limit,所以答案是:

SELECT f.id, 
       f.front, 
       f.back, 
       h.statusChangedIdCode, 
       h.whenCreated,
       h.historyIdCode 
FROM dpod_site_flashcards AS f 
   JOIN dpod_site_historyItems AS h ON f.id = h.itemId 
WHERE f.id = 216 
  AND historyIdCode = 'statusChanged' 
ORDER BY h.whenCreated
limit 1

SQL Server和Sybase支持top,导致:

SELECT top 1 f.id, 
       f.front, 
       f.back, 
       h.statusChangedIdCode, 
       h.whenCreated,
       h.historyIdCode 
FROM dpod_site_flashcards AS f 
   JOIN dpod_site_historyItems AS h ON f.id = h.itemId 
WHERE f.id = 216 
  AND historyIdCode = 'statusChanged' 
ORDER BY h.whenCreated

Oracle使用rownum,但您需要一个子查询:

select * from (SELECT f.id, 
       f.front, 
       f.back, 
       h.statusChangedIdCode, 
       h.whenCreated,
       h.historyIdCode 
FROM dpod_site_flashcards AS f 
   JOIN dpod_site_historyItems AS h ON f.id = h.itemId 
WHERE f.id = 216 
  AND historyIdCode = 'statusChanged' 
ORDER BY h.whenCreated
) t
where rownum = 1

DB2使用fetch_first:

SELECT f.id, 
       f.front, 
       f.back, 
       h.statusChangedIdCode, 
       h.whenCreated,
       h.historyIdCode 
FROM dpod_site_flashcards AS f 
   JOIN dpod_site_historyItems AS h ON f.id = h.itemId 
WHERE f.id = 216 
  AND historyIdCode = 'statusChanged' 
ORDER BY h.whenCreated
fetch first 1 row only