mySQL - отображать только наиболее распространенные и все другие комбинации столбцов показывают 0 - PullRequest
0 голосов
/ 09 декабря 2018

Я пытаюсь вычислить наибольшее количество аварий в одной гонке, которое было у любой машины, поэтому у машины может быть несколько аварий в одной гонке (образно).У меня есть таблица сбоев со следующими столбцами:

c_raceName, c_raceDate, c_raceId и другие не относящиеся к делу.

Во-первых, чтобы однозначно идентифицировать расу, в которую он входит вraceName и raceDate пара.И чтобы однозначно идентифицировать сбой, вы должны использовать эту пару вместе с raceId.

Так что все эти столбцы фактически принадлежат другой таблице, которая является нашей Entry таблицей.Эта таблица содержит информацию об автомобилях, которые участвуют в гонках.В этой таблице есть следующие столбцы:

e_raceId, e_raceDate, e_raceName, e_raceEntryCarId, e_raceEntryDriverId.

Я понял, что не каждая раса будет участвоватьв таблицу Crash, поэтому я считаю, что я должен либо ссылаться на таблицу Entry из таблицы Crash, либо наоборот.

Более того, что, если данные еще не были включены для гонок, а пара данных raceName и raceDate существует только в таблице Race, которая содержит r_raceName и r_raceDate базовая информация.

Так что я думаю, что мне, возможно, придется сделать это SELECT из таблицы Crash и JOIN до таблицы Entry и далее до таблицы Raceчтобы действительно получить все пары raceName и raceDate.Хотя я понятия не имею, как мне тогда написать условие, которое говорит, что если этих пар нет в таблице 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

и т. Д.

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Ваш вопрос состоит из нескольких частей.Если вы хотите 0 значений, то вам нужно внешнее соединение или коррелированный подзапрос.Я предполагаю, что у вас есть стол со всеми расами, но select distinct на столе entries также работает.

Тогда, если вы хотите больше всего аварий на машину , вам нужен идентификатор автомобиля в таблице 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;
0 голосов
/ 09 декабря 2018

Обратите внимание, что вам не нужно 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 <> скрипка здесь

...