mySQL-仅显示最常见的列,所有其他列组合均显示0

时间:2018-12-09 01:11:46

标签: mysql sql count distinct

我正在尝试计算任何一场比赛中任何一辆汽车发生的最高撞车次数,因此,一辆汽车可能在一次比赛中发生多次撞车(图)。我有以下几行崩溃的表:

c_raceNamec_raceDatec_raceId和其他无关紧要的东西。

首先,要唯一标识一个种族,将其分为raceNameraceDate对。为了唯一地识别崩溃,您必须在raceId旁边使用该对。

因此,所有这些列实际上都属于另一个表,即我们的Entry表。该表包含参加比赛的汽车的信息。该表包括以下列:

e_raceIde_raceDatee_raceNamee_raceEntryCarIde_raceEntryDriverId

我已经意识到并不是所有种族都将被输入到Crash表中,所以我相信我要么必须引用Entry表中的Crash表,要么反过来。

此外,如果竞赛条目尚未包含数据,并且raceNameraceDate对数据仅存在于保存{{1 }}和Race基本信息。

所以我认为我可能要做的是从r_raceName表中r_raceDate,然后从SELECTCrash表,再到{{1 }}表以真正获取所有JOINEntry对。尽管我不知道如何写一个条件来说明如果Race表中不存在这些对,那么在我的输出中我希望它们的值为0或使它们存在实际上在我的输出中。

所以我已经走了这么远:

raceName

产生以下输出:

raceDate

所以我已经能够将它们分为3和1,如上所示,尽管我只希望显示最多的崩溃,所以希望显示3行。我也希望所有没有崩溃的比赛都显示为0,而不是根本不显示。所以我想要的输出是:

Crash

2 个答案:

答案 0 :(得分:1)

请注意,使用select distinct时不需要group by

SELECT
    l.c_raceName  AS raceName
  , l.c_raceDate  AS raceDate
  , COUNT( * )    AS mostCrashes
FROM Crashes l
GROUP BY
    l.c_raceName  
  , l.c_raceDate
HAVING COUNT( * ) = 0
OR COUNT( *) = (
    SELECT
        MAX( mostCrashes )
    FROM (
        SELECT
            l.c_raceName        AS raceName
          , l.c_raceDate        AS raceDate
          , COUNT( l.c_raceId ) AS mostCrashes
        FROM Crashes l
        GROUP BY
            l.c_raceName  
          , l.c_raceDate
    ) sq
)
ORDER BY
    mostCrashes
;

如果您使用的是MySQL 8或更高版本,则可以使用通用表表达式(cte)简化该过程。

WITH cte
AS (
    SELECT
        l.c_raceName AS raceName
      , l.c_raceDate AS raceDate
      , COUNT( * )   AS mostCrashes
    FROM Crashes l
    GROUP BY
        l.c_raceName  
      , l.c_raceDate
)
SELECT
    *
FROM cte
WHERE mostCrashes = ( SELECT MAX( mostCrashes ) FROM cte )
OR mostCrashes  = 0
ORDER BY
    mostCrashes
;

如果只想要一行,则另一种方法是按计算列对结果进行排序(降序排列)并将结果限制为一行。是

SELECT
    l.c_raceName        AS raceName
  , l.c_raceDate        AS raceDate
  , COUNT( l.c_raceId ) AS mostCrashes
FROM Crashes l
GROUP BY
    l.c_raceName  
  , l.c_raceDate
ORDER BY
    mostCrashes DESC
LIMIT 1

修改

CREATE TABLE Crashes(
   c_raceName varchar(40)  NOT NULL
  ,c_raceDate varchar(40)  NOT NULL
);
INSERT INTO Crashes(c_raceName,c_raceDate) 
    VALUES
      ('Race 1','2018/01/21')
    , ('Race 1','2018/01/21')
    , ('Race 1','2018/01/21')
    , ('Race 2','2018/01/21')
    , ('Race 2','2018/01/21')
    , ('Race 2','2018/01/21')
    , ('Race 2','2018/01/21')
    , ('Race 2','2018/01/21')
    , ('Race 1','2018/09/11')
    , ('Race 1','2016/03/14');
    ;
SELECT
    l.c_raceName        AS raceName
  , l.c_raceDate        AS raceDate
  , COUNT( l.c_raceDate ) AS mostCrashes
FROM Crashes l
GROUP BY
    l.c_raceName
  , l.c_raceDate
HAVING COUNT( l.c_raceDate ) = 0
OR COUNT( l.c_raceDate ) = (
    SELECT
        MAX( mostCrashes )
    FROM (
        SELECT
            l.c_raceName        AS raceName
          , l.c_raceDate        AS raceDate
          , COUNT( l.c_raceDate ) AS mostCrashes
        FROM Crashes l
        GROUP BY
            l.c_raceName
          , l.c_raceDate
    ) sq
)
ORDER BY
    mostCrashes
;
raceName | raceDate   | mostCrashes
:------- | :--------- | ----------:
Race 2   | 2018/01/21 |           5
WITH cte
AS (
    SELECT
        l.c_raceName        AS raceName
      , l.c_raceDate        AS raceDate
      , COUNT( l.c_raceDate ) AS mostCrashes
    FROM Crashes l
    GROUP BY
        l.c_raceName
      , l.c_raceDate
)
SELECT
    *
FROM cte
WHERE mostCrashes = ( SELECT MAX( mostCrashes ) FROM cte )
OR mostCrashes  = 0
ORDER BY
    mostCrashes
;
raceName | raceDate   | mostCrashes
:------- | :--------- | ----------:
Race 2   | 2018/01/21 |           5

db <>提琴here

答案 1 :(得分:1)

您的问题分为多个部分。如果需要fwrite()值,则需要一个外部联接或相关子查询。我想您有一个包含所有种族的表格,但是0表格上的select distinct也适用。

然后,如果您希望每辆车死机次数最多,则在entries表中需要一个 car 标识符。我敢肯定有一个(这很有意义),但是您没有在问题中描述它。我猜是类似crashes的东西。

结果查询如下:

c_raceEntryCarId

如果您只想知道每场比赛的撞车次数,则子查询会有所不同:

select e_racename, e.e_racedate,
       (select count(*)
        from crashes c
        where c.c_racename = e.e_racename and c.e_racedate = e.e_race_date 
        group by c.c_raceEntryCarId
        order by count(*) desc
        limit 1
       ) as most_crashes
from (select e.e_racename, e.e_racedate
      from entries e
      group by e.e_racename, e.e_racedate
     ) e;