MySQL Query - вычислить значения между несколькими таблицами и сгруппировать по идентификатору

у меня есть таблица игроков, таблица статистики и таблица стоимости опций. примеры ниже

ИГРОКИ

идентификатор имя фамилия 1 Джон кузнец 2 Джо кузнец

СТАТИСТИКА

идентификатор игрока круглый pass_yd pass_td pass_int 1 1 130 2 0 2 1 246 2 1

OPTIONS_VALUES

идентификатор option_name option_value 1 pass_yd 0,04 2 pass_td 6 3 pass_int -2

У меня есть следующий запрос:

SELECT
    (SELECT s.pass_yd * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'pass_yd') AS pass_yd_pt
    , (SELECT s.pass_td * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'pass_td') AS pass_td_pt
    , (SELECT s.pass_int * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'pass_int') AS pass_int_pt
    , (SELECT s.rush_yd * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'rush_yd') AS rush_yd_pt
    , (SELECT s.rush_td * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'rush_td') AS rush_td_pt
    , (SELECT s.rec * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'rec') AS rec_pt
    , (SELECT s.rec_yd * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'rec_yd') AS rec_yd_pt
    , (SELECT s.rec_td * o.option_value FROM stats AS s, options_values AS o WHERE o.option_name = 'rec_td') AS rec_td_pt

Если я укажу в каждом операторе SELECT, что такое player_id, я могу получить ожидаемое значение, все в одной строке.

Что id LIKE нужно сделать, так это иметь возможность запрашивать полный список игроков с помощью оператора GROUP BY, но у меня проблемы с этим. Я чувствую, что я близко, но явно пропускаю шаг.

Было бы лучше, если бы таблица stats имела отдельные строки для каждой статистики, а не помещала их в столбцы. Тогда вы можете просто присоединиться к stats и option_values в этой колонке.

Barmar 16.12.2020 23:56

Не могли бы вы привести пример ожидаемого результата GROUP BY на основе примеров таблиц?

llmora 17.12.2020 00:23

@Barmar, так есть таблица со столбцами player_id, round, stat_name, stat_value? Я этого не учел. интересный...

zubar 18.12.2020 17:45
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
3
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Сверните таблицу options_values в одну строку, которую вы можете перекрестно соединить с stats, чтобы получить соответствующие множители.

SELECT p.id, p.firstname, p.lastname, s.round, 
    s.pass_yd * o.pass_yd AS pass_yd_pt,
    s.pass_td * o.pass_td AS pass_td_pt,
    ...
FROM players AS p
JOIN stats AS s ON p.id = s.player_id
CROSS JOIN (SELECT 
        MAX(IF(option_name = 'pass_yd', option_value, NULL)) AS pass_yd,
        MAX(IF(option_name = 'pass_td', option_value, NULL)) AS pass_td,
        ...
    FROM options_values) AS o

Вы бы попробовали использовать Common Table Expressions

таким образом

WITH 
    cteStat as (
        select playerid , 'pass_yd' as option_name  , pass_yd as value 
        union 
        select playerid , 'pass_td' as option_name  , pass_td as value 
        union 
        select playerid , 'pass_int' as option_name     , pass_int as value 
    )

Затем присоединитесь к этому с OPTIONS_VALUES, используя столбец option_name.

Это не сработало для меня, я полагаю, потому что MySQL еще не допускает операторы WITH?

zubar 18.12.2020 17:45

Вероятно, вы можете сделать что-то вроде этого:

SELECT playerid,
    SUM(CASE WHEN o.option_name = 'pass_yd' 
             THEN s.pass_yd * o.option_value 
             ELSE 0 END) AS pass_yd_pt, 

    SUM(CASE WHEN o.option_name = 'pass_td' 
             THEN s.pass_td * o.option_value 
             ELSE 0 END) AS pass_td_pt,

    SUM(CASE WHEN o.option_name = 'pass_int' 
             THEN s.pass_int * o.option_value 
             ELSE 0 END) AS pass_int_pt 
 FROM stats AS s 
 CROSS JOIN options_values AS o 
 GROUP BY playerid;

Вы делаете CROSS JOIN (заменяя запятую, которую вы сделали) только один раз и комбинацию SUM(CASE ..) в SELECT с соответствующими условиями.

Демо здесь: https://www.db-fiddle.com/f/ighbPMv8tbpKnU2hBYkiVz/0

Другие вопросы по теме