3

以下 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 的一行?

在此处输入图像描述

4

4 回答 4

6
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

当您选择多个行时,这两种情况也适用dpod_site_flashcards.id,而 LIMIT 解决方案不会这样做。

于 2013-01-09T20:48:39.997 回答
3

试过这个?

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 

-编辑

糟糕,感谢@Gordon,没有足够仔细地阅读要求。这是一些应该完成这项工作的SQLFiddle 。

这是正确代码的片段——将其包含在您的 WHERE 子句中:

h.whenCreated = (select max(whenCreated)
   from dpod_site_historyItems h2
   where h2.itemId = h.itemId)
于 2013-01-09T20:40:43.870 回答
1

如果你使用 MySQL,将 end 更改为:ORDER BY h.whenCreated DESC LIMIT 1

于 2013-01-09T20:40:59.770 回答
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
于 2013-01-09T21:05:21.793 回答