Текущая сумма, исключая строки с повторяющимся значением столбца

#sql #sql-server #tsql #window-functions

Вопрос:

Пример таблицы:

Видео кодирование потраченное видео время кодирование байтов кодирование байтов в сумме сумма времени, затраченного на видео (ожидаемое) video time spent running sum (actual)
A 1 1 500 500 1 1
A 2 1 400 900 1 2
B 3 2 300 1200 3 5
B 4 2 200 1400 3 8
B 5 2 100 1500 3 11
B 6 2 100 1600 3 14
  • в столбце «затраченное видео» указано, сколько времени было просмотрено видео; какая кодировка была просмотрена, не имеет значения.
  • видео-время, потраченное на бег, — это то, что я пытаюсь получить. Он должен суммировать только время, проведенное на уровне видео, игнорируя кодировки.

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

Мой вопрос до сих пор:

 SELECT * FORM (  SELECT   ...,  SUM(encoding_bytes) OVER(ORDER BY encoding_bytes desc) AS encoding_bytes_running_sum,   SUM(video_time_spent) OVER (ORDER BY encoding_bytes desc) AS video_time_spent_running_sum  ... )  WHERE video_time_spent_running_sum lt; X  

но video_time_spent_running_sum недостаточно умен, чтобы пропускать другие кодировки в одном и том же видео. Каков был бы лучший способ сделать это?

количество кодировок на видео не является постоянным.

скрипт для создания таблицы:

 SELECT  *,  SUM(encoding_bytes) OVER(  ORDER BY  encoding_bytes DESC  ) AS encoding_bytes_running_sum,  SUM(video_time_spent) OVER (  ORDER BY  encoding_bytes DESC ROWS UNBOUNDED PRECEDING  ) AS video_time_spent_running_sum FROM (  VALUES  ('a', 1, 1, 500),  ('a', 2, 1, 400),  ('b', 3, 2, 300),  ('b', 4, 2, 200),  ('b', 5, 2, 100),  ('b', 6, 2, 100) ) AS t (video, encoding, video_time_spent, encoding_bytes)  

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

1. Вы когда-нибудь сталкивались с тем, чтобы видео (например, A) имело другое время для другой кодировки?

2. @ДалеК, спасибо! исправлен сценарий. все кодировки в одном и том же видео имеют одинаковое время.

Ответ №1:

Один из способов сделать это заключается в следующем (я уверен, что его можно упростить); где вы используете ROW_NUMBER функцию только для подсчета первой строки каждого видео.

 WITH cte AS (  SELECT  *  , SUM(encoding_bytes) OVER (ORDER BY encoding_bytes DESC) AS encoding_bytes_running_sum  --, SUM(video_time_spent) OVER (ORDER BY encoding_bytes DESC ROWS UNBOUNDED PRECEDING) AS video_time_spent_running_sum  , ROW_NUMBER() OVER (PARTITION BY video ORDER BY video, [encoding]) rn  FROM (  VALUES  ('a', 1, 1, 500),  ('a', 2, 1, 400),  ('b', 3, 2, 300),  ('b', 4, 2, 200),  ('b', 5, 2, 100),  ('b', 6, 2, 100)  ) AS t (video, [encoding], video_time_spent, encoding_bytes) ) SELECT video, [encoding], video_time_spent, encoding_bytes, encoding_bytes_running_sum  , SUM(CASE WHEN rn = 1 THEN video_time_spent ELSE 0 END) OVER (ORDER BY video ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) video_time_spent_running_sum FROM cte;  

Это возвращает:

кодирование видео видео_тайм_расход кодирование_байтов кодирование_bytes_running_sum video_time_spent_running_sum
a 1 1 500 500
a 2 1 400 900
b 3 2 300 1200
b 4 2 200 1400
b 5 2 100 1600
b 6 2 100 1600