2013-11-03 87 views
0

我有一張學生姓名錶,自動增加了NR記錄,但是在記錄的每次編輯時,都會創建一個新記錄,將NR複製到ID字段。 但是,當我嘗試對MAX記錄中的ID記錄進行分組時,它顯示了該ID的最大數量,但是當我詢問剩餘的rocord時,它沒有向我顯示該組ID的最後一個記錄顯示包含最新編輯版本的所有記錄

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 
+2

可以顯示示例數據,因爲它是查詢的所需結果嗎?目前尚不清楚你試圖達到什麼目標。 – peterm

回答

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

+0

太棒了,它的工作原理! 最近3天我一直在爲此苦苦掙扎。 你是一個活的節省;-) –

+1

@ user2811590如果你覺得這是正確的答案,請upvote並將其標記爲正確的:) – tftd

0

儘管@Gordon Linoff的答案在技術上是正確的,但在大型數據集上使用sub-queries可能更耗費資源和更多時間。

根據具體情況,我通常將數據分爲兩個表studentsstudent_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)即可。這將始終返回學生細節的最新版本。

插入一個新的學生

  1. 插入一個學生
    INSERT INTO students(student_id) VALUES('');
  2. 獲取持續插入ID
    SELECT LAST_INSERT_ID();(讓我們說這個例子的目的返回1)
  3. 插入學生細節
    INSERT INTO student_details(student_id, first_name, last_name, gender) VALUES('1', 'Alice', 'Carper', 'f')

更新現有學生(假設student_id數據= 1)

  1. 將所有以前student_detail 「版本」 的 「歷史」:
    UPDATE student_details SET is_history = true WHERE student_details.student_id = 1 AND is_history = false
  2. 添加全新改版:
    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)

相關問題