【问题标题】:mySQL - Only display most common & all other column combinations show 0mySQL - 仅显示最常见的 & 所有其他列组合显示 0
【发布时间】:2018-12-09 01:11:45
【问题描述】:

我正在尝试计算任何汽车在单场比赛中发生的最高撞车次数,因此一辆汽车可能在一场比赛中发生多次撞车事故(形象地)。我有一个包含以下列的崩溃表:

c_raceNamec_raceDatec_raceId 和其他不相关的。

首先,为了唯一标识一个种族,它以raceNameraceDate 对出现。要唯一识别崩溃,您必须将此对与 raceId 一起使用。

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

e_raceIde_raceDatee_raceNamee_raceEntryCarIde_raceEntryDriverId

我已经意识到并不是每场比赛都会进入Crash 表,所以我相信我要么必须参考Crash 表中的Entry 表,要么反过来。

此外,如果还没有包含比赛条目的数据,并且 raceNameraceDate 对数据仅存在于包含 r_raceNamer_raceDate 基本信息的 Race 表中,该怎么办? .

所以我相信我可能需要做的是SELECTCrash 表,JOINEntry 表,再到Race 表才能真正获得所有raceNameraceDate 对。虽然我不知道如何编写一个条件来说明如果这些对不存在于Crash 表中,那么在我的输出中我希望它们被赋予 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

等等

【问题讨论】:

    标签: mysql sql count distinct


    【解决方案1】:

    您的问题有多个部分。如果你想要0 值,那么你需要一个外连接或相关子查询。我想你有一张包含所有种族的桌子,但entries 桌子上的select distinct 也可以。

    然后,如果您希望每辆车 发生最多的事故,您需要在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;
    

    如果您只想要每场比赛的崩溃次数,子查询会有点不同:

    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;
    

    【讨论】:

    • 每个raceNameraceDate 组合的唯一标识符是raceId,因此只需将c.c_raceEntryCarId 替换为c.c_raceId。尽管我不确定如何使用SELECT DISTINCTNULL 值替换为0,但这似乎效果很好。我已经在most_crashesSELECT 上尝试了 IFNULL() 函数,尽管它似乎对我的输出完全没有影响。现在将尝试使用外部联接。
    【解决方案2】:

    请注意,使用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 或更高版本,您可以使用公用表表达式 (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
    ;
    
    种族名 |比赛日期 |大多数崩溃 :------- | :--------- | ----------: 比赛 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
    ;
    
    种族名 |比赛日期 |大多数崩溃 :------- | :--------- | ----------: 比赛 2 | 2018/01/21 | 5

    db小提琴here

    【讨论】:

    • 谢谢大家,在您的第一个回答中,sq 代表什么?
    • "sq" 只是一个子查询别名,在 MySQL 中可能不需要,但我在需要的地方使用 SQL Server 进行验证
    • 您在顶部的答案实际上并没有输出任何信息,如果它更容易理解,我已经提炼并添加了数据到我的问题中。您的答案运行,但根本没有输出任何行。
    • 数据在哪里?我所看到的只是几行查询输出 - 不允许查询运行。您可以在rextester.com/l/mysql_online_compilerdbfiddle.uk 设置小提琴
    • 再试一次这些查询。
    猜你喜欢
    • 1970-01-01
    • 2021-06-26
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多