【问题标题】:Mysql SELECT distinct Group by and Order byMysql SELECT distinct Group by 和 Order by
【发布时间】:2015-05-28 09:18:56
【问题描述】:

我的 SQL SELECT 语句有问题。我得到了正确的顺序,正确的驱动程序,但我的其他列不正确!而且我无法正确理解。

我有这样的数据:

id,     races_id,   drivers_id,     drive_nr,   lap_nr,     time,           dnf
"231",  "9",        "41",           "1",        "1",        "00:00:04.750", "0"
"232",  "9",        "41",           "1",        "2",        "00:00:06.030", "0"
"233",  "9",        "41",           "1",        "3",        "00:00:01.740", "0"
"234",  "9",        "42",           "1",        "1",        "00:00:05.440", "0"
"235",  "9",        "42",           "1",        "2",        "00:00:05.400", "0"
"236",  "9",        "42",           "1",        "3",        "00:00:02.300", "0"
"237",  "9",        "43",           "1",        "1",        "00:00:00.620", "0"
"238",  "9",        "43",           "1",        "2",        "00:00:00.290", "0"
"239",  "9",        "43",           "1",        "3",        "00:00:00.280", "0"
"240",  "9",        "44",           "1",        "1",        "00:00:00.600", "0"
"241",  "9",        "44",           "1",        "2",        "00:00:00.190", "0"
"242",  "9",        "44",           "1",        "3",        "00:00:00.220", "0"
"243",  "9",        "45",           "1",        "1",        "00:00:02.830", "0"
"244",  "9",        "45",           "1",        "2",        "00:00:01.890", "0"
"245",  "9",        "45",           "1",        "3",        "00:00:03.200", "0"
"246",  "9",        "46",           "1",        "1",        "00:00:03.580", "0"
"247",  "9",        "46",           "1",        "2",        "00:00:04.550", "0"
"248",  "9",        "46",           "1",        "3",        "00:00:01.060", "0"
"249",  "9",        "47",           "1",        "1",        "00:00:02.920", "0"
"250",  "9",        "47",           "1",        "2",        "00:00:03.950", "0"
"251",  "9",        "47",           "1",        "3",        "00:00:00.320", "0"
"252",  "9",        "48",           "1",        "1",        "00:00:02.150", "0"
"253",  "9",        "48",           "1",        "2",        "00:00:05.720", "0"
"254",  "9",        "48",           "1",        "3",        "00:00:04.530", "0"
"255",  "9",        "49",           "1",        "1",        "00:00:01.530", "0"
"256",  "9",        "49",           "1",        "2",        "00:00:04.360", "0"
"257",  "9",        "49",           "1",        "3",        "00:00:07.110", "0"
"258",  "9",        "50",           "1",        "1",        "00:00:00.450", "0"
"259",  "9",        "50",           "1",        "2",        "00:00:03.550", "0"
"260",  "9",        "50",           "1",        "3",        "00:00:07.900", "0"

查询这个:

SELECT  `id` ,  
    `races_id` ,  
    `drivers_id` ,  
    `drive_nr` ,  
    `lap_nr` , 
    MIN( `time` ) AS TIME,  
    `dnf` 
FROM  `laps` 
WHERE  `races_id` =9 
GROUP BY  drivers_id` 
ORDER BY MIN(  `time` ) ASC 

我明白了:

id,     races_id,   drivers_id,     drive_nr,   lap_nr,     time,           dnf
240,    9,          44,             1,          1,          00:00:00.190,   0
237,    9,          43,             1,          1,          00:00:00.280,   0
249,    9,          47,             1,          1,          00:00:00.320,   0
258,    9,          50,             1,          1,          00:00:00.450,   0
246,    9,          46,             1,          1,          00:00:01.060,   0
255,    9,          49,             1,          1,          00:00:01.530,   0
231,    9,          41,             1,          1,          00:00:01.740,   0
243,    9,          45,             1,          1,          00:00:01.890,   0
252,    9,          48,             1,          1,          00:00:02.150,   0
234,    9,          42,             1,          1,          00:00:02.300,   0

所以我以正确的顺序得到正确的时间列,而不是像ID, drive_nr, lap_nr, dnf这样的其他列

如何修复我的查询以在最短时间和正确的其他数据下获得不同的 drivers_id?

【问题讨论】:

  • 问题是您按驱动程序 ID 分组,并获取 MIN 时间。所有其他字段既不是聚合字段,也不是 group by 子句,因此它们来自哪一行的值是不确定的。您需要获得最快圈速,然后将其连接回表格以获取其他字段。

标签: mysql group-by sql-order-by


【解决方案1】:

如果你删除“GROUP BY”

SELECT  `id` ,  `races_id` ,  `drivers_id` ,  `drive_nr` ,  `lap_nr` , MIN( `time` ) AS TIME,  `dnf` FROM  `laps` WHERE  `races_id` = 9 ORDER BY MIN(  `time` ) ASC

Take a look on this link, use of group by and min

【讨论】:

  • 我不需要 1 位最佳单圈车手。我需要所有车手中最好的单圈车手
【解决方案2】:

问题在于 GROUP BY 将行分组在一起以形成聚合函数。在标准 SQL 中,返回的每一列都必须在 group by 子句或聚合字段中提及,但 MySQL 对此进行了扩展。

尽管 MySQL 确实允许返回额外的列,但它没有指定这些列的值来自哪一行。虽然有一个模式(我认为似乎是插入的最后一行),但这没有定义并且可能会改变。

要获取其他字段,您有几个选择。

最简单的方法是有一个子查询来获取驾驶员 ID 和该驾驶员 ID 的一圈最短时间,然后将其连接回圈表(加入驾驶员 ID 和时间)顶部获取值匹配行的其他字段。这有几个小的缺点。首先,MySQL 不会使用子查询字段上的索引来加入主表,但数据有限可能不是问题(除了在慢查询日志中弹出查询的烦恼)。第二个问题是,如果有人在 2 圈之间共享最佳单圈时间。

简单的sql示例:-

SELECT a.id,  
    a.races_id,  
    a.drivers_id,  
    a.drive_nr,  
    a.lap_nr, 
    mt.min_time,
    a.dnf 
FROM laps a
INNER JOIN
(
    SELECT  drivers_id ,  
        MIN( `time` ) AS min_time
    FROM  laps 
    WHERE  races_id = 9 
    GROUP BY  drivers_id 
) mt
ON a.drivers_id = mt.drivers_id
AND a.`time` = mt.min_time
WHERE  a.races_id = 9 
ORDER BY min_time ASC 

如果您确实有 2 圈具有相同的最短圈速,那么您需要指定要返回哪些详细信息(或者您可能不在乎,也可能在外部查询中滥用 GROUP BY)。

第二种解决方案是,您在按车手 ID 和单圈时间排序的结果中为每一行生成一个序列号,并在车手 ID 更改时重置序列号。然后丢弃没有序列为 1 的任何一圈。但是更难阅读,并且当您有大量数据时可能会非常慢。

示例如下(未测试):-

SELECT id,  
        races_id,  
        drivers_id,  
        drive_nr,  
        lap_nr, 
        `time`,
        dnf
FROM
(
    SELECT id,  
            races_id,  
            drivers_id,  
            drive_nr,  
            lap_nr, 
            `time`,
            dnf,
            @ctr := IF(drivers_id = @did, @ctr + 1, 1) AS ctr,
            @did := drivers_id
    FROM
    (
        SELECT id,  
                races_id,  
                drivers_id,  
                drive_nr,  
                lap_nr, 
                `time`,
                dnf 
        FROM laps 
        WHERE  races_id = 9
        ORDER BY drivers_id, `time`
    )
    CROSS JOIN
    (
        SELECT @ctr := 0, @did := 0
    ) sub1
) sub2
WHERE ctr = 1
ORDER BY `time`

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-22
    • 2011-10-09
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多