我的表存储了我的CMS条目的修订数据。每个条目都有一个ID和修订日期,并且有多个修订版本:
Table: old_revisions
+----------+---------------+-----------------------------------------+
| entry_id | revision_date | entry_data |
+----------+---------------+-----------------------------------------+
| 1 | 1302150011 | I like pie. |
| 1 | 1302148411 | I like pie and cookies. |
| 1 | 1302149885 | I like pie and cookies and cake. |
| 2 | 1288917372 | Kittens are cute. |
| 2 | 1288918782 | Kittens are cute but puppies are cuter. |
| 3 | 1288056095 | Han shot first. |
+----------+---------------+-----------------------------------------+
我想将部分数据传输到另一个表:
Table: new_revisions
+--------------+----------------+
| new_entry_id | new_entry_data |
+--------------+----------------+
| | |
+--------------+----------------+
我想将entry_id
和entry_data
转移到new_entry_id
和new_entry_data
。但我只想转移每个条目的最新版本。
我得到了这个问题:
INSERT INTO new_revisions (
new_entry_id,
new_entry_data
)
SELECT
entry_id,
entry_data,
MAX(revision_date)
FROM old_revisions
GROUP BY entry_id
但我认为问题在于我试图将3列数据插入2列。
如何在不转移修订日期的情况下根据修订日期传输数据?
答案 0 :(得分:3)
您可以使用以下查询:
insert into new_revisions (new_entry_id, new_entry_data)
select o1.entry_id, o1.entry_data
from old_revisions o1
inner join
(
select max(revision_date) maxDate, entry_id
from old_revisions
group by entry_id
) o2
on o1.entry_id = o2.entry_id
and o1.revision_date = o2.maxDate
见SQL Fiddle with Demo。此查询获取每个max(revision_date)
的{{1}},然后在entry_id
和最大日期连接回您的表,以获取要插入的行。
请注意,子查询仅返回entry_id
和日期,这是因为我们要将entry_id
应用于选择列表中不在聚合函数中的项目。 MySQL使用GROUP BY
子句的扩展,允许选择列表中的列被排除并聚合,但这可能会导致意外结果。通过仅包括聚合所需的列和group by将确保结果是您想要的值。 (见MySQL Extensions to GROUP BY)
来自MySQL文档:
MySQL扩展了GROUP BY的使用,因此选择列表可以引用GROUP BY子句中未命名的非聚合列。 ...您可以通过避免不必要的列排序和分组来使用此功能来获得更好的性能。但是,当GROUP BY中未命名的每个非聚合列中的所有值对于每个组都相同时,这非常有用。服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。此外,添加ORDER BY子句不会影响每个组中值的选择。选择值后会对结果集进行排序,而ORDER BY不会影响服务器选择的值。
答案 1 :(得分:2)
如果您想输入最后一个条目,则需要在以下条目之前对其进行过滤:
select entry_id, max(revision_date) as maxDate
from old_revisions
group by entry_id;
然后将其用作子查询来过滤所需的数据:
insert into new_revisions (new_entry_id, new_entry_data)
select entry_id, entry_data
from old_revisions as o
inner join (
select entry_id, max(revision_date) as maxDate
from old_revisions
group by entry_id
) as a on o.entry_id = a.entry_id and o.revision_date = a.maxDate