#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 |