mySQL - 只显示最常见的 & 所有其他列组合显示 0

mySQL - Only display most common & all other column combinations show 0

我正在尝试计算任何汽车在单场比赛中发生的撞车事故的最高次数,因此一辆汽车可能在一场比赛中发生多次撞车事故(比喻)。我遇到了以下列 table 次崩溃:

c_raceNamec_raceDatec_raceId 和其他不相关的。

首先,为了唯一标识一个种族,它出现在 raceNameraceDate 对中。要唯一标识崩溃,您必须将这对与 raceId.

一起使用

所以所有这些列实际上都属于另一个 table,也就是我们的 Entry table。这个 table 包含了参赛车辆的信息。此 table 包含以下列:

e_raceId, e_raceDate, e_raceName, e_raceEntryCarId, e_raceEntryDriverId.

我意识到并不是每场比赛都会进入 Crash table,所以我相信我要么必须参考 Entry table 来自Crash table,或者反过来。

此外,如果尚未包含比赛条目的数据,并且 raceNameraceDate 对数据仅存在于 Race table 上怎么办?其中包含 r_raceNamer_raceDate 基本信息。

所以我认为我可能需要做的是 SELECTCrash table 和 JOINEntry table,并进一步进入 Race table 以真正获得所有 raceNameraceDate 对。虽然我不知道我将如何编写一个条件来说明如果这些对不存在于 Crash table 中,那么在我的输出中我希望它们的值为 0,或者事实上,让它们出现在我的输出中。

所以我已经走到这一步了:

SELECT DISTINCT l.c_raceName AS raceName, 
l.c_raceDate AS raceDate, 
COUNT( l.c_raceId) AS mostCrashes 

FROM Crashes l
GROUP BY l.c_raceId
;

正在生成以下内容的输出:

raceName | raceDate | mostCrashes
---------------------------------
Race 1   |2018/01/21| 1
Race 1   |2018/01/21| 3
...      | ...      | ...

所以我已经能够将它们分开,如上所示分为 3 和 1,尽管我只希望显示最多的崩溃,所以第 3 行。此外,我希望所有没有发生任何崩溃的比赛都显示为 0,而不是根本不显示。所以我正在寻找的输出是:

raceName | raceDate | mostCrashes
---------------------------------
Race 1   |2018/01/21| 3
Race 2   |2018/01/21| 5
Race 1   |2018/09/11| 0
Race 1   |2016/03/14| 0

等等

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

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 或更高版本,您可以使用通用 table 表达式 (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
;

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

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<>fiddle here

你的问题有多个部分。如果你想要 0 值,那么你需要一个外部连接或相关子查询。我想你在所有比赛中都有一个 table,但是 entries table 上的 select distinct 也可以。

然后,如果您希望每辆车发生最多车祸,您需要 car crashes table 中的标识符].我确定那里有一个(这很有意义),但是您没有在问题中描述它。我猜它类似于 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;

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

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
       ) as most_crashes
from (select e.e_racename, e.e_racedate
      from entries e
      group by e.e_racename, e.e_racedate
     ) e;