Как в этом случае работает SQL count(distinct)?

#sql #count

Вопрос:

Я пытаюсь найти матч№, в котором Германия играла против Польши. Это от https://www.w3resource.com/sql-exercises/soccer-database-exercise/sql-subqueries-exercise-soccer-database-4.php. Есть две таблицы : match_details и soccer_country. Я не понимаю, как в этом случае работает счетчик(отдельный). Может кто-нибудь прояснить, пожалуйста? Спасибо!

 SELECT match_no 
FROM match_details 
WHERE team_id = (
    SELECT country_id 
    FROM soccer_country 
    WHERE country_name = 'Germany') 
  OR team_id = (
    SELECT country_id 
    FROM soccer_country 
    WHERE country_name = 'Poland') 
GROUP BY match_no 
HAVING COUNT(DISTINCT team_id) = 2;
 

Комментарии:

1. боже, какой запутанный способ это сделать. В любом случае, поскольку каждый матч показывается дважды (по одному разу на команду/страну), HAVING COUNT(DISTINCT team_id) = 2 мы просто проверяем, показывают ли результаты один матч

2. Эй, Ламак, извини, я все еще не понимаю. Итак, счетчик(отдельный идентификатор команды) будет проверять наличие отдельного идентификатора команды для каждого матча, верно? Но разве тогда не было бы так для каждого матча_но? Так как каждый идентификатор team_id отличается…

Ответ №1:

Как упоминал Ламак, какое уродливое соображение для запроса, но есть много способов подойти к запросу.

Как уже упоминалось, подсчет (Отдельный идентификатор команды) гарантирует, что существует только 2 уникальные команды. Если когда-либо будет получен декартов результат, вы можете получить повторение нескольких строк, показывающих более одного экземпляра обеих команд. Таким образом, количество пользователей в TEAM_ID исключает это.

Тем не менее, в других структурах данных запросов «команды», которые я видел, есть одна запись для матча и столбец для КАЖДОЙ КОМАНДЫ, играющей в матче. Это проще с помощью долгосрочного, но все же относительно простого запроса.

Немного разбейте запрос и рассмотрите крупномасштабный набор данных (не то, чтобы у этого или любой другой профессиональной лиги было бы такое большое количество записей, чтобы дать задержку с помощью sql-движка).

Ваш первый критерий — игры с Германией. Так что давайте начнем с этого.

 SELECT 
      md1.match_no 
   FROM 
      match_details md1
         JOIN soccer_country sc1
            on md1.team_id = sc1.country_id
            AND sc1.country_name = 'Germany'
 

Итак, зачем вообще смотреть на какую-либо другую запись/матч, если Германия даже не является частью матча ни с одной из сторон. Из которых это само по себе вернет 6 совпадений из выборки данных 51 совпадения. Итак, теперь все, что вам нужно сделать, это снова присоединиться к таблице сведений о матчах во второй раз только для этих матчей, но и вторая команда-Польша

 SELECT 
      md1.match_no 
   FROM 
      match_details md1
         JOIN soccer_country sc1
            on md1.team_id = sc1.country_id
            AND sc1.country_name = 'Germany'
         -- joining again for the same match Germany was already qualified
         JOIN match_details md2
            on md1.match_no = md2.match_no
            -- but we want the OTHER team record since Germany was first team
            and md1.team_id != md2.team_id
            -- and on to the second country table based on the SECOND team ID
            JOIN soccer_country sc2
               on md2.team_id = sc2.country_id
               -- and the second team was Poland
               AND sc2.country_name = 'Poland'
 

Да, может быть более длинный запрос, но, исключив 45 других совпадений (опять же, подумав о БОЛЬШОЙ базе данных), вы уже сохранили тонны данных в очень ограниченном наборе. И теперь заканчиваю только те, что Германия / Польша. Никаких агрегатов, подсчетов, различий, только прямые соединения.

Отзывы

Давайте взглянем на некоторые ПЛОХИЕ примеры данных… которых, как известно всем программистам, нет (НЕТ). В любом случае, давайте взглянем на эти несколько совпадений.

 Match    Team ID    blah
52       Poland     Just put the names here for simplistic purposes
52       Poland
53       Germany
53       Germany
 

Если бы вы выполнили запрос без ОТДЕЛЬНЫХ команд, то появились бы совпадения 52 и 53… Поскольку Польша является одной командой и появляется 2 раза в матче 52, и аналогично Германия 2 раза в матче 53. Делая ОТДЕЛЬНУЮ команду, вы можете видеть, что для каждого матча возвращается только 1 команда и, следовательно, исключается. Это помогает? Опять же, нет такой вещи, как плохие данные 🙂

И еще один пример матча, в котором более 2 команд создали

 Match    Team ID    
54       France     
54       Poland
54       England
55       Hungary
56       Austria
 

В каждом из этих матчей НИ ОДИН из них не будет возвращен. В матче 54 есть 3 разные команды, а в матчах 55 и 56 есть только один участник, поэтому соперников нет.

2-я ОБРАТНАЯ СВЯЗЬ

Чтобы уточнить запрос. Если вы посмотрите на короткий запрос только для Германии, этот псевдонимный экземпляр «md1» уже находится на любой заданной записи для матча с Германией. Так что во втором присоединении к «md2» я забочусь только об одном и том же матче, поэтому я могу присоединиться к одному и тому же матчу_но. Однако в псевдониме «md2″»! = «означает» НЕ РАВНО». ! = логично НЕТ. Таким образом, объединение означает, что из MD1 присоединитесь к псевдониму MD2 с тем же идентификатором соответствия. Однако, только дайте мне, где команды НЕ одинаковые. Таким образом, первый экземпляр содержит идентификатор команды Германии (уже квалифицированный) и, таким образом, дает мне идентификатор вторичной команды. Так что теперь я могу использовать идентификатор команды вторичного экземпляра (md2) для подключения к стране для подтверждения только для Польши.

Теперь это все проясняет для вас?

Комментарии:

1. Эй, ДРапп..спасибо за твой ответ. Но не могли бы мы просто вернуться к этому: «Подсчет (отдельный идентификатор команды) гарантирует, что существует только 2 уникальные команды. «Если мы сгруппируем по match_no и уже указали Германию и Польшу для team_id (из моего кода), то результатом будет только уникальный match_no, верно? Какое отношение к этому имеет подсчет различных идентификаторов team_id?

2. @рахул, см. Пересмотренный ответ с ЧЕТКИМИ разъяснениями.

3. Эй, Драпп, спасибо за разъяснение. Еще один вопрос: в вашем коде, где вы использовали исключительно объединения, не могли бы вы объяснить, почему вам нужно было создать md2?ВЫБЕРИТЕ md1.match_no ИЗ match_details md1 ПРИСОЕДИНИТЬСЯ К soccer_country sc1 на md1.team_id = sc1.country_id И sc1.имя_страны = «Германия» И «Польша». Уилл, это не сработает так, как сейчас? Кроме того, почему вы должны присоединяться к md1 с md2? и какова функция оператора»!»? Извините, я всего лишь новичок, и поэтому у меня много сомнений…

4. @рахул, я снова отвечу за тебя.

5. Эй, Драпп, да, это все объясняет. Большое спасибо!