Как СУММИРОВАТЬ с отсутствующими числами, замененными последними записями - PullRequest
0 голосов
/ 28 мая 2020

Предположим, в игре 5 уровней, и для каждого уровня игроки могут набрать 1, 2 и 3. Игрок X имеет следующие данные:

Level | Attempt | Score
1     | 1       | 2  
1     | 2       | 3
2     | 1       | 3
3     | 1       | 3
4     | 1       | 1
4     | 2       | 3
5     | 1       | 2
5     | 2       | 2
5     | 3       | 3

Теперь я хочу SUM количество очков GROUP BY попытка, но особым образом:

Попытка 1: просто 2 + 3 + 3 + 1 + 3 = 12

Попытка 2: Теперь, когда выполняются уровни 2 и 3 нет Попытки 2, но я все еще хочу использовать их самый последний результат для сложения: 3 + 3 + 3 + 3 + 2 = 14

Попытка 3: Опять же, я хочу сложить все уровни с их наибольшим количеством недавний результат (если нет попытки 3), поэтому я получаю 3 + 3 + 3 + 3 + 3 = 15

Как я могу сделать это с помощью SQL? Обратите внимание, что нет ограничений на количество попыток , поэтому игрок может фактически пройти уровень 100 раз, а я должен предоставить 100 сумм.

1 Ответ

0 голосов
/ 31 мая 2020

Тогда это может быть что-то вроде этого:

WITH
-- your input ...
input(level,attempt,score) AS (
          SELECT 1,1,2
UNION ALL SELECT 1,2,3
UNION ALL SELECT 2,1,3
UNION ALL SELECT 3,1,3
UNION ALL SELECT 4,1,1
UNION ALL SELECT 4,2,3
UNION ALL SELECT 5,1,2
UNION ALL SELECT 5,2,2
UNION ALL SELECT 5,3,3
)
-- your input ends here
, -- replace comma with WITH in real query ..
-- creating a table with 5 rows per each of the 3 attempts
frame (level,attempt) AS (
  SELECT
     i.level
   , a.attempt
   FROM input i
   CROSS JOIN (
     SELECT DISTINCT
       attempt
     FROM input
    ) a
   WHERE i.attempt=1
)
-- SELECT * FROM frame; -- un-comment this line to test the frame table
,
gapfilled AS (
-- Query before GROUPing: left join the frame table with the input table
-- and fill the resulting NULLs using the LAST_VALUE ( ... IGNORE NULLS) 
-- OLAP function. If you can take a previous one, pick it, if not , pick
-- a following one. 
-- Vertica has named OLAP windows, which we use here - one forward, one backward
  SELECT
    frame.level
  , NVL(
      LAST_VALUE(input.attempt IGNORE NULLS) OVER(fwd)
    , LAST_VALUE(input.attempt IGNORE NULLS) OVER(bwd)
    )  AS attempt
  , NVL(
      LAST_VALUE(input.score   IGNORE NULLS) OVER(fwd) 
    , LAST_VALUE(input.score   IGNORE NULLS) OVER(bwd)
    )  AS score
  FROM frame LEFT JOIN input USING(level,attempt)
  WINDOW fwd AS (PARTITION BY frame.attempt ORDER BY frame.level)
  ,      bwd AS (PARTITION BY frame.attempt ORDER BY frame.level DESC)
)
-- SELECT * FROM gapfilled ORDER BY 2,1; -- UN-comment to test gapfilled table
SELECT
  attempt
, SUM(score) AS score_sum
FROM gapfilled
GROUP BY
  attempt;
-- out  attempt | score_sum 
-- out ---------+-----------
-- out        1 |        11
-- out        2 |        14
-- out        3 |        15

...