我有一个包含学生姓名的表格,自动增加了NR
条记录,但是在记录的每次编辑中,都会创建一个新的,将NR
复制到ID
字段。
但是当我尝试在MAX(NR
)时对ID记录进行分组时,它会向我显示该ID的最大数量,但是当我要求剩余的rocord时,它并没有显示该组的最后一条记录
SELECT MAX(`NR`) AS 'mNr',`NR`,`ID`,`Name1`,`Name3`,`Gender`
FROM `Kids` GROUP BY `ID`
这会产生如下结果:
mNr NR ID Name1 Name3 Gender 252 1 1 Alice Carper f 179 2 2 Dorah Fisher f 189 3 3 Racheal King f 173 4 4 Frank Smith m 192 5 5 Patrick Fay m 305 6 6 Gloria Sing f 299 7 7 Bridget Young f
但正如您所看到的,查询显示最高编辑NR,但随后继续给出记录其余部分中的最低值,而不是属于该最新NR的记录详细信息... 我究竟做错了什么? 这是样本数据:
NR ID Name1 Name3 Gender
1 1 Alice Achand f
2 2 Dorah Achieng f
3 3 Racheal Achieng f
4 4 Francisca Adikin f
5 5 Patrick Adilu m
6 6 Gloria Ajwang f
7 7 Bridget Aketch f
130 5 Patrick Adilu m
129 4 Francisca Adikin f
128 2 Dorah Achieng f
153 4 Francisca Adikin f
173 4 Francisca Adikin f
179 2 Dorah Achieng f
189 3 Racheal Achieng f
192 5 Patrick Adilu m
252 1 Alice Wor f
299 7 Bridget Aketch f
305 6 Gloria Ajwang f
答案 0 :(得分:0)
也许不知道它,你正在使用MySQL的一个神秘功能。 MySQL允许您在聚合查询的select
语句中包含不在聚合函数或group by
子句中的列。引擎为这些列输入任意值。
正确的方式来做你想要的是一个连接:
SELECT k.*
FROM `Kids` k join
(select id, max(nr) as maxnr
from kids
group by id
) m
on k.id = m.id and nr = maxnr;
以下是文档中的明确说明:
MySQL扩展了GROUP BY的使用,以便选择列表可以引用 未在GROUP BY子句中命名的非聚合列。这意味着 前面的查询在MySQL中是合法的。您可以使用此功能 通过避免不必要的列排序来获得更好的性能 分组。但是,这主要适用于每个中的所有值 GROUP BY中未命名的非聚合列对于每个列都是相同的 组。服务器可以自由选择每个组中的任何值,所以 除非它们相同,否则所选择的值是不确定的。 此外,不能从每个组中选择值 受添加ORDER BY子句的影响。对结果集进行排序 选择值后发生,ORDER BY不影响 服务器选择的每个组中的值。
您可以更详细地阅读here。
答案 1 :(得分:0)
虽然@Gordon Linoff的答案在技术上是正确的,但在大型数据集上使用sub-queries可能会更耗费资源和时间。
根据具体情况,我通常会将数据分为两个表students
和student_details
students
的表结构是
CREATE TABLE students (
student_id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT
);
此表的想法是为学生创建一个唯一的号码,并存储您可能不想在修订版中保存的任何其他学生数据。
student_details
的表结构是:
CREATE TABLE student_details (
revision_id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
student_id INTEGER NOT NULL,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
gender VARCHAR(1),
is_history BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT FOREIGN KEY(student_id) REFERENCES students(student_id) ON DELETE RESTRICT
);
此表存储学生的实际数据。更新某个学生的数据后,您只需将is_history
列更新为true
以获取该学生的记录。然后,在选择学生数据时,您只需使用SELECT student_details.* FROM students LEFT JOIN student_details ON (student_details.student_id = students.student_id AND student_details.is_history = false)
。这将始终返回学生详细信息的最新版本。
插入新学生
INSERT INTO students(student_id) VALUES('');
SELECT LAST_INSERT_ID();
(假设为了此示例,它返回1)INSERT INTO student_details(student_id, first_name, last_name, gender) VALUES('1', 'Alice', 'Carper', 'f')
更新现有学生(假设student_id = 1)
UPDATE student_details SET is_history = true WHERE student_details.student_id = 1 AND is_history = false
INSERT INTO student_details(student_id, first_name, last_name, gender) VALUES('1', 'Alice', 'Achand', 'f')
获取学生及其最新学生资料
SELECT student_details.* FROM students LEFT JOIN student_details ON (student_details.student_id = students.student_id AND student_details.is_history = false)