Собесов

Betera: выгрузка игроков, выполнивших бонус по киберспорту

SQLУсловные агрегацииСредняяJunior

Условие

Выгрузить игроков, которые с 12:00 14.03.2022 сделали ставку в пре-матч на события раздела «Киберспорт». Условия Бонусного предложения:

  • Минимальная сумма ставки — 10 BYN.
  • Коэффициент в одиночке ≥ 1.5; в экспрессе на киберспорт — каждый исход с к-ом ≥ 1.5.
  • Ставка должна быть рассчитана не позднее 12:00 15.03.2022.
  • Ставки вида «система» не учитываются.
  • CashOut, возвраты и FreeBet не участвуют.

Решение

Подход

Достаточно одного запроса с WHERE, агрегирующим суммы ставок по игроку, плюс HAVING на сумму. Допущение по схеме: есть таблица bets(user_id, bet_id, bet_type, stake, status, settle_time, created_time) и bet_legs(bet_id, sport, market_type, odds).

Реализация

WITH eligible_bets AS (
  SELECT b.bet_id, b.user_id, b.stake
  FROM bets b
  WHERE b.created_time >= TIMESTAMP '2022-03-14 12:00'
    AND b.settle_time <= TIMESTAMP '2022-03-15 12:00'
    AND b.bet_type IN ('single','express')                  -- без 'system'
    AND b.is_freebet = FALSE
    AND b.is_cashout = FALSE
    AND b.status NOT IN ('return','void')
    AND b.stake >= 10
    -- Все ноги — киберспорт, пре-матч, к ≥ 1.5
    AND NOT EXISTS (
      SELECT 1
      FROM bet_legs l
      WHERE l.bet_id = b.bet_id
        AND (l.sport <> 'esports'
          OR l.market_type <> 'prematch'
          OR l.odds < 1.5)
    )
)
SELECT DISTINCT user_id
FROM eligible_bets;

Python-аналог

mask = (
    df.created_time >= "2022-03-14 12:00"
) & (df.settle_time <= "2022-03-15 12:00") & (df.stake >= 10) & \
   (df.bet_type.isin(["single","express"])) & (~df.is_freebet) & (~df.is_cashout)
 
bad = legs[(legs.sport != "esports") | (legs.market_type != "prematch") | (legs.odds < 1.5)]
df = df[mask & ~df.bet_id.isin(bad.bet_id.unique())]
print(df.user_id.unique())

Подводные камни

  1. «Все ноги ≥ 1.5» — проверяется через NOT EXISTS ноги с odds < 1.5. Иначе для одиночек с одной ногой условие тривиально, но для экспресса нужно именно «во всех ногах».
  2. Часовой пояс: 12:00 14.03 локально — уточнить TZ в данных.
  3. Возвраты могут быть зашиты в status или в отдельный флаг — проверить схему.
  4. CashOut обычно фиксируется отдельной строкой с уменьшенной суммой; считать стоит исходную ставку.

Эталонный ответ

Фильтр по времени, типу ставки, отсутствию ноги вне киберспорта/прематча/к<1.5, минимальной сумме — затем DISTINCT user_id.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти