每个比赛距离的男性和女性 SQLite 最佳三倍
SQLite best three times for men and women for each race distance
我从这个简单的查询开始,它为我提供了在 125 公里比赛中取得最佳成绩(第一、第二和第三)的三个人。
SELECT *
FROM Coureurs
WHERE Genre=’M’ AND Epreuve='125km' AND TempsPassage IS NOT NULL
ORDER BY TempsPassage
LIMIT 3;
但是,我还需要在该距离上表现最好的三位女性(类型=F)。
以及其他每个距离的最佳三名男子和三名女子(TempsPassage=80km/65km/40km,..)。
这远远超出了我的水平...我真的想避免构建单独的“硬编码”查询。
提前致谢,
皮埃尔
进行以下assumptions/changes
Epreuve 列是数字(存储 125、80 .... 而不是 125km、80km ....)
- 125km 和 80km 如果排序的话,80km 大于 125km
- 文本值会花费一些额外的存储空间
- 如果需要,可以很容易地提取附加 km 的值,例如
SELECT genre, Epreuve||'km', TempsPassage, Name FROM Coureurs
TempsPassage 列存储时间(示例使用秒但参见 Time Values)
假设以下数据:-
还假设您想要一个相对简单易懂的单个查询,那么以下内容可能适合:-
WITH
m125 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
f125 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
m80 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
f80 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
m65 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
f65 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
m40 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3),
f40 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3)
SELECT * FROM m125
UNION SELECT * FROM f125
UNION SELECT * FROM m80
UNION SELECT * FROM f80
UNION SELECT * FROM m65
UNION SELECT * FROM f65
UNION SELECT * FROM m40
UNION SELECT * FROM f40
ORDER BY Epreuve DESC,Genre DESC, TempsPassage ASC
;
这利用了所谓的 CTE(通用 Table 表达式),它们基本上是临时表。
每个 Genre 和 Epreuve 的排列使用一个 CTE (2 * 4 = 8),它是用类似的查询构建的。
创建所有 CTE 后,使用 UNION 组合 8 个单独的临时表。
使用结果上方的数据是(显然您可能希望对结果进行不同的排序):-
下面是SQL用来测试上面的内容并创建结果:-
DROP TABLE IF EXISTS Coureurs;
CREATE TABLE IF NOT EXISTS Coureurs (Genre TEXT, Epreuve int, TempsPassage int, name TEXT);
INSERT INTO Coureurs VALUES
('M',125,600,'Fred'),('M',125,610,'Bert'),('M',125,630,'Harry'),('M',125,620,'Albert'),('M',125,575,'David')
,('F',125,615,'Mary'),('F',125,625,'Anne'),('F',125,601,'Betty'),('F',125,625,'Sue'),('F',125,670,'Shelia')
,('F',80,450,'Louise'),('F',80,460,'Celia'),('F',80,425,'Debra'),('F',80,475,'Diana')
,('F',65,350,'Zara'),('F',65,360,'Yvonne'),('F',65,325,'Wilma'),('F',65,375,'Ursurla')
,('F',40,250,'Tracy'),('F',40,260,'Rhona'),('F',40,225,'Samantha'),('F',40,275,'Karen')
,('M',80,450,'Lou'),('M',80,460,'Colin'),('M',80,425,'Danny'),('M',80,475,'Eddy')
,('M',65,350,'Zed'),('M',65,360,'Mark'),('M',65,325,'William'),('M',65,375,'Tom')
,('M',40,250,'Jim'),('M',40,260,'Larry'),('M',40,225,'Peter'),('M',40,275,'Ronald')
;
SELECT * FROM Coureurs ORDER BY Random();
/* Easiest to understand - combining individual queries as CTE
CTE = Common Table Expression (equates to temporary table)
*/
WITH
m125 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
f125 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
m80 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
f80 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
m65 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
f65 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
m40 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3),
f40 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3)
SELECT * FROM m125
UNION SELECT * FROM f125
UNION SELECT * FROM m80
UNION SELECT * FROM f80
UNION SELECT * FROM m65
UNION SELECT * FROM f65
UNION SELECT * FROM m40
UNION SELECT * FROM f40
ORDER BY Epreuve DESC,Genre DESC, TempsPassage ASC
;
DROP TABLE IF EXISTS Coureurs;
您可以使用 window 函数 ROW_NUMBER()
对每个 race/genre 的结果进行排名,然后过滤到 return 只有排名 1-3:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Epreuve, Genre ORDER BY TempsPassage) rn
FROM Coureurs
WHERE TempsPassage IS NOT NULL
)
WHERE rn <= 3
ORDER BY (Epreuve + 0), Genre, rn
如果出现平局,则可以尝试 RANK()
window 函数而不是 ROW_NUMBER()
。
我从这个简单的查询开始,它为我提供了在 125 公里比赛中取得最佳成绩(第一、第二和第三)的三个人。
SELECT *
FROM Coureurs
WHERE Genre=’M’ AND Epreuve='125km' AND TempsPassage IS NOT NULL
ORDER BY TempsPassage
LIMIT 3;
但是,我还需要在该距离上表现最好的三位女性(类型=F)。 以及其他每个距离的最佳三名男子和三名女子(TempsPassage=80km/65km/40km,..)。
这远远超出了我的水平...我真的想避免构建单独的“硬编码”查询。 提前致谢, 皮埃尔
进行以下assumptions/changes
Epreuve 列是数字(存储 125、80 .... 而不是 125km、80km ....)
- 125km 和 80km 如果排序的话,80km 大于 125km
- 文本值会花费一些额外的存储空间
- 如果需要,可以很容易地提取附加 km 的值,例如
SELECT genre, Epreuve||'km', TempsPassage, Name FROM Coureurs
TempsPassage 列存储时间(示例使用秒但参见 Time Values)
假设以下数据:-
还假设您想要一个相对简单易懂的单个查询,那么以下内容可能适合:-
WITH
m125 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
f125 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
m80 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
f80 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
m65 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
f65 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
m40 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3),
f40 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3)
SELECT * FROM m125
UNION SELECT * FROM f125
UNION SELECT * FROM m80
UNION SELECT * FROM f80
UNION SELECT * FROM m65
UNION SELECT * FROM f65
UNION SELECT * FROM m40
UNION SELECT * FROM f40
ORDER BY Epreuve DESC,Genre DESC, TempsPassage ASC
;
这利用了所谓的 CTE(通用 Table 表达式),它们基本上是临时表。
每个 Genre 和 Epreuve 的排列使用一个 CTE (2 * 4 = 8),它是用类似的查询构建的。
创建所有 CTE 后,使用 UNION 组合 8 个单独的临时表。
使用结果上方的数据是(显然您可能希望对结果进行不同的排序):-
下面是SQL用来测试上面的内容并创建结果:-
DROP TABLE IF EXISTS Coureurs;
CREATE TABLE IF NOT EXISTS Coureurs (Genre TEXT, Epreuve int, TempsPassage int, name TEXT);
INSERT INTO Coureurs VALUES
('M',125,600,'Fred'),('M',125,610,'Bert'),('M',125,630,'Harry'),('M',125,620,'Albert'),('M',125,575,'David')
,('F',125,615,'Mary'),('F',125,625,'Anne'),('F',125,601,'Betty'),('F',125,625,'Sue'),('F',125,670,'Shelia')
,('F',80,450,'Louise'),('F',80,460,'Celia'),('F',80,425,'Debra'),('F',80,475,'Diana')
,('F',65,350,'Zara'),('F',65,360,'Yvonne'),('F',65,325,'Wilma'),('F',65,375,'Ursurla')
,('F',40,250,'Tracy'),('F',40,260,'Rhona'),('F',40,225,'Samantha'),('F',40,275,'Karen')
,('M',80,450,'Lou'),('M',80,460,'Colin'),('M',80,425,'Danny'),('M',80,475,'Eddy')
,('M',65,350,'Zed'),('M',65,360,'Mark'),('M',65,325,'William'),('M',65,375,'Tom')
,('M',40,250,'Jim'),('M',40,260,'Larry'),('M',40,225,'Peter'),('M',40,275,'Ronald')
;
SELECT * FROM Coureurs ORDER BY Random();
/* Easiest to understand - combining individual queries as CTE
CTE = Common Table Expression (equates to temporary table)
*/
WITH
m125 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
f125 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 125 ORDER BY TempsPassage ASC LIMIT 3),
m80 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
f80 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 80 ORDER BY TempsPassage ASC LIMIT 3),
m65 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
f65 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 65 ORDER BY TempsPassage ASC LIMIT 3),
m40 AS (SELECT * FROM Coureurs WHERE genre = 'M' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3),
f40 AS (SELECT * FROM Coureurs WHERE genre = 'F' AND Epreuve = 40 ORDER BY TempsPassage ASC LIMIT 3)
SELECT * FROM m125
UNION SELECT * FROM f125
UNION SELECT * FROM m80
UNION SELECT * FROM f80
UNION SELECT * FROM m65
UNION SELECT * FROM f65
UNION SELECT * FROM m40
UNION SELECT * FROM f40
ORDER BY Epreuve DESC,Genre DESC, TempsPassage ASC
;
DROP TABLE IF EXISTS Coureurs;
您可以使用 window 函数 ROW_NUMBER()
对每个 race/genre 的结果进行排名,然后过滤到 return 只有排名 1-3:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Epreuve, Genre ORDER BY TempsPassage) rn
FROM Coureurs
WHERE TempsPassage IS NOT NULL
)
WHERE rn <= 3
ORDER BY (Epreuve + 0), Genre, rn
如果出现平局,则可以尝试 RANK()
window 函数而不是 ROW_NUMBER()
。