假設我在 SQLite 中運行以下命令:
CREATE TABLE my_table
(
id INTEGER PRIMARY KEY,
NAME VARCHAR(20),
date DATE,
num INTEGER,
important VARCHAR(20)
);
INSERT INTO my_table (NAME, date, num, important)
VALUES ('A', '2000-01-01', 10, 'Important 1');
INSERT INTO my_table (NAME, date, num, important)
VALUES ('A', '2000-02-01', 20, 'Important 2');
INSERT INTO my_table (NAME, date, num, important)
VALUES ('A', '1999-12-01', 30, 'Important 3');
該表如下所示:
| ID | 姓名 | 日期 | 數量 | 重要的 |
|---|---|---|---|---|
| 1 | 一種 | 2000-01-01 | 10 | 重要 1 |
| 2 | 一種 | 2000-02-01 | 20 | 重要 2 |
| 3 | 一種 | 1999-12-01 | 30 | 重要 3 |
如果我執行:
SELECT id
FROM my_table
GROUP BY NAME;
結果是:
----
| id |
----
| 1 |
----
如果我執行:
SELECT id, MAX(date)
FROM my_table
GROUP BY NAME;
結果是:
---- ------------
| id | max(date) |
---- ------------
| 2 | 2000-02-01 |
---- ------------
如果我執行:
SELECT id,
MAX(date),
MAX(num)
FROM my_table
GROUP BY NAME;
結果是:
---- ------------ ----------
| id | max(date) | max(num) |
---- ------------ ----------
| 3 | 2000-02-01 | 30 |
---- ------------ ----------
我的問題是,這個定義明確嗎?具體來說,我是否保證id = 2在執行第二個查詢時總是得到(使用單個Max(date)聚合),或者這只是 SQLite 如何排序表以獲取Max分組之前的副作用?
我問這個是因為我特別想要id = 2. 然后我將執行另一個查詢來選擇該important行的欄位(對于我的實際問題,第一個查詢將回傳多個ids,我將一次選擇important所有這些行的所有欄位。
此外,這一切都發生在 iOS 核心資料查詢中,因此我無法執行更復雜的子查詢。如果我知道 a 的順序GROUP BY是由聚合定義的,那么我會非常有信心我的查詢不會中斷(直到 Apple 為 Core Data 放棄 SQLite)。
謝謝!
uj5u.com熱心網友回復:
來自 Sqlite 手冊
2.5. 聚合查詢中的裸列
通常的情況是聚合查詢中的所有列名要么是聚合函式的引數,要么出現在 GROUP BY 子句中。包含不在聚合函式內且未出現在 GROUP BY 子句(如果存在)中的列名的結果列稱為“裸”列。例子:
SELECT a, b, sum(c) FROM tab1 GROUP BY a;
在上面的查詢中,“a”列是 GROUP BY 子句的一部分,因此輸出的每一行都包含“a”的不同值之一。“c”列包含在 sum() 聚合函式中,因此輸出列是“a”具有相同值的行中所有“c”值的總和。但是裸列“b”的結果是什么?答案是“b”結果將是形成聚合的輸入行之一中“b”的值。問題是您通常不知道哪個輸入行用于計算“b”,因此在許多情況下,“b”的值是未定義的。
當聚合函式為 min() 或 max() 時,會發生特殊處理。例子:
SELECT a, b, max(c) FROM tab1 GROUP BY a;
在聚合查詢中使用 min() 或 max() 聚合函式時,結果集中的所有裸列都從輸入行中獲取值,該行還包含最小值或最大值。因此在上面的查詢中,輸出中“b”列的值將是具有最大“c”值的輸入行中“b”列的值。如果兩個或多個輸入行具有相同的最小值或最大值,或者如果查詢包含多個 min() 和/或 max() 聚合函式,則仍然存在歧義。只有內置的 min() 和 max() 函式以這種方式作業。
如果裸列出現在缺少 GROUP BY 子句的聚合查詢中,并且輸入行數為零,則裸列的值是任意的。例如,在這個查詢中:
SELECT count(*), b FROM tab1;
如果 tab1 表不包含任何行(count(*) 的計算結果為 0),那么裸列“b”將具有任意且無意義的值。
大多數其他 SQL 資料庫引擎不允許裸列。如果在查詢中包含裸列,其他資料庫引擎通常會引發錯誤。在查詢中包含裸列的能力是 SQLite 特定的擴展。
https://www.sqlite.org/lang_select.html
uj5u.com熱心網友回復:
我是否保證在執行第二個查詢時總是得到 id = 2(使用單個 Max(date) 聚合),或者這只是 SQLite 如何在分組之前訂購表以獲取 Max 的副作用?
是的,您得到的結果是有保證的,因為它記錄在聚合查詢的裸列中。
id您獲得的列的值來自包含 max 的行date。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/375479.html
