Как выполнить другой запрос на основе возвращаемого значения? - PullRequest
6 голосов
/ 19 марта 2019

У меня есть список футбольных матчей, определенных следующим образом:

id |        datetime      | status | gameweek | round_id | home_team_id
 1   2019-03-31 00:00:00      1          29     12696          1243
 2   2019-03-31 00:00:00      1          29     12696          1248
 3   2019-03-31 00:00:00      1          29     12696          1242
 4   2019-03-31 00:00:00      1          29     12696          1246
 5   2019-03-31 00:00:00      1          29     12696          1244
 6   2019-03-31 00:00:00      1          29     12696          1247
 7   2019-03-31 20:30:00      1          29     12696          1241
 8   2019-03-31 00:00:00      1          29     12696          1249
 9   2019-03-31 00:00:00      1          29     12696          2981
 10  2019-03-31 00:00:00      1          29     12696          1259

Мне нужно вернуть все matches, которые имеют gameweek, следующие gameweek к окончанию matches, а не все.

Некоторые rounds не имеют gameweek, поэтому в этом случае должны быть возвращены все matches, которые имеют datetime рядом с готовым match.

Я написал следующий запрос:

Select m.* from `match` m where round_id = 12696 and m.datetime = (SELECT COALESCE(MIN(CASE WHEN m2.status < 5 THEN m2.datetime END), MAX(m2.datetime)) FROM `match` m2 WHERE m2.round_id = m.round_id)

это возвращает только 9 записей, и я не понимаю почему, единственная причина в том, что у одной записи тоже есть время.

Что значит законченный matches?

Для matches закончен или закончен, я имею в виду, что статус каждого match равен 5 или 3. Статус 1 означает, что match запланирован, но еще не играл; 5 означает finished и 3 отменены.

например:

id |        datetime      | status | gameweek | round_id | home_team_id
 1   2019-03-20 00:00:00      5          29     12696          1243
 2   2019-03-20 00:00:00      5          29     12696          1248
 3   2019-03-20 00:00:00      5          29     12696          1242
 4   2019-03-31 00:00:00      1          29     12696          1246
 5   2019-03-31 00:00:00      1          29     12696          1244
 6   2019-03-31 00:00:00      1          29     12696          1247
 7   2019-03-31 20:30:00      1          29     12696          1241
 8   2019-03-31 00:00:00      1          29     12696          1249
 9   2019-03-31 00:00:00      1          29     12696          2981
 10  2019-03-31 00:00:00      1          29     12696          1259

Как видите, первые три записи уже проиграны. В этом случае запрос должен вернуть все matches (проигранные и запланированные), поскольку gameweek 29 содержит также другие matches, которые еще не воспроизводились, поэтому ожидаемый результат - все 10 записей.

ожидаемый результат : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Другая важная вещь заключается в том, что некоторые round не имеют gameweek, поэтому предположим, что нам нужно вернуть предстоящий matches, например:

id |        datetime      | status | gameweek | round_id | home_team_id
 1   2019-03-20 00:00:00      5        NULL     12696          1243
 2   2019-03-20 00:00:00      5        NULL     12696          1248
 3   2019-03-20 00:00:00      5        NULL     12696          1242
 4   2019-03-31 00:00:00      1        NULL     12696          1246
 5   2019-03-31 00:00:00      1        NULL     12696          1244
 6   2019-03-31 00:00:00      1        NULL     12696          1247
 7   2019-03-31 20:30:00      1        NULL     12696          1241
 8   2019-03-31 00:00:00      1        NULL     12696          1249
 9   2019-03-31 00:00:00      1        NULL     12696          2981
 10  2019-03-31 00:00:00      1        NULL     12696          1259

ожидаемый результат : 4, 5, 6, 7, 8, 9, 10

(в скрипке запись 7 отсутствует).

Если нет gameweeks, но все matches завершены (статус 5), то нам нужно вернуть все matches самого последнего datetime, например:

id |        datetime      | status | gameweek | round_id | home_team_id
 1   2019-03-20 00:00:00      5        NULL     12696          1243
 2   2019-03-20 00:00:00      5        NULL     12696          1248
 3   2019-03-20 00:00:00      5        NULL     12696          1242
 4   2019-03-31 00:00:00      5        NULL     12696          1246
 5   2019-03-31 00:00:00      5        NULL     12696          1244
 6   2019-03-31 00:00:00      5        NULL     12696          1247
 7   2019-03-31 20:30:00      5        NULL     12696          1241
 8   2019-03-31 00:00:00      5        NULL     12696          1249
 9   2019-04-05 00:00:00      5        NULL     12696          2981
 10  2019-04-05 00:00:00      5        NULL     12696          1259

ожидаемый результат : 9, 10

id |        datetime      | status | gameweek | round_id | home_team_id
 1   2019-03-20 00:00:00      5        28     12696          1243
 2   2019-03-20 00:00:00      5        28     12696          1248
 3   2019-03-20 00:00:00      1        28     12696          1242
 4   2019-03-31 00:00:00      1        28     12696          1246
 5   2019-04-05 00:00:00      5        29     12696          1244
 6   2019-04-05 00:00:00      5        29     12696          1247
 7   2019-04-05 20:30:00      5        29     12696          1241
 8   2019-04-05 00:00:00      5        29     12696          1249

Ожидаемый результат: 1,2,3,4,

Я создал скрипку , которая охватывает все случаи.

Ответы [ 4 ]

2 голосов
/ 27 марта 2019

Это выглядит как излишне сложный запрос, но он соответствует выводам, указанным выше. Может быть хорошей отправной точкой.

with current_round as (
    select * 
    from match_case_1
    where round_id = 12696
)
select *
from current_round cr
where
    (
        not exists(select * from current_round where gameweek is null)
    )
    or 
    (
        exists(select * from current_round where status = 1) 
        and not exists(select * from current_round where gameweek is not null)
        and cr.status = 1    
    )
    or 
    (
        not exists(select * from current_round where status = 1)
        and not exists(select * from current_round where gameweek is not null)
        and cast(cr.`datetime` as date) = (
            select max(cast(`datetime` as date)) as `date`
            from current_round
            where status = 5 or status = 3
        )
    );

EDIT

Запросы Fiddle к БД по опубликованным сценариям

  1. https://www.db -fiddle.com / ж / 2f7NEPo72tUM7zLHBX2GXQ / 0
  2. https://www.db -fiddle.com / ж / 3ghG6zf7hv2SbACL9vtnJa / 1
  3. * ** 1022 тысяча двадцать-одна * -fiddle.com / ж / q7DgtJRfDxyPA8bQheRncA / 1
  4. https://www.db -fiddle.com / ж / tV7VhZg1Ywfx1YmnFMtZdh / 1
1 голос
/ 28 марта 2019

Поскольку не похоже, что ваши совпадения будут меняться очень часто, я бы посоветовал избавить себя от головной боли и разделить эти запросы на уровне приложения (если таковой существует)

Исходя из ваших примеров, вы можете задать своей БД ряд вопросов, чтобы получить желаемые результаты

Есть ли наименьшая игровая неделя с незавершенными матчами за раунд 12696?

SELECT MIN(gameweek) min_gameweek 
  FROM `match` 
 WHERE round_id = 12696
   AND gameweek IS NOT NULL
   AND status = 1

Если да .. Какие совпадения для этой игровой недели?

SELECT *
  FROM `match` 
 WHERE round_id = 12696
   AND gameweek = :min_gameweek

Если нет .. (вы можете попытаться найти здесь максимальную игровую неделю для завершенных матчей в раунде 12696 и перечислить все матчи из этого списка)

Если все еще нет .. Какие незаконченные матчи без игровой недели в раунде 12696?

SELECT *
  FROM `match`
 WHERE round_id = 12696
   AND gameweek IS NULL
   AND status = 1

Если нет .. Это самое позднее время для законченного матча без игровой недели в раунде 12696?

SELECT MAX(`datetime`) latest_datetime
  FROM `match`
 WHERE round_id = 12696
   AND gameweek IS NULL
   AND status != 1

Если да .. Каковы завершенные матчи без игровой недели в раунде 12696, для которых установлено последнее время?

SELECT *
  FROM `match` 
 WHERE round_id = 12696
   AND `datetime` = :latest_datetime

N.B. Этот подход включает в себя больше запросов, но он гораздо более читабелен, отлаживаем и гибок, и может даже работать лучше, чем попытка выполнить один запрос монстра

Возможно, вы могли бы объединить некоторые из приведенных выше запросов с добавлением слишком большого количества непрозрачности, но я все равно начал бы с написания каждого шага и его тестирования

Я бы также серьезно предложил упростить весь процесс следующим образом

  • Сохранять текущую игровую неделю и максимальную игровую неделю для каждого раунда в круглом столе (NULLed, если в этом раунде нет игровых недель)
  • Просто показать все совпадения текущей недели игры для рассматриваемого раунда
  • Когда матч заканчивается (или в конце дня / недели), увеличивайте текущую игровую неделю, если все матчи завершены и максимум еще не достигнут
0 голосов
/ 19 марта 2019

Это то, что вы хотите?:

SELECT m.*
FROM `match` m 
WHERE m.round_id = 48 AND 
      m.gameweek = (SELECT MAX(m1.gameweek) 
                    FROM `match` m1 
                    WHERE m1.round_id = m.round_id AND m1.status = 1
                   );

Таким образом, вы получите последний сыгранный gameweek за каждый матч.

0 голосов
/ 19 марта 2019

просто используйте 1-недельный фильтр будущего

 select m.* from `match` m 
 WHERE DATE(datetime)>=date(now())
 and DATE(datetime) <= date_add(current_date, INTERVAL 1 week)       
 and m.status =1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...