У меня есть таблица со следующими данными

Task | Start Time        | End Time
A    | 2/24/2020 1:00 PM | 2/24/2020 2:00 PM
B    | 2/24/2020 3:00 PM | 2/24/2020 5:00 PM
A    | 2/25/2020 1:00 PM | 2/25/2020 2:00 PM
B    | 2/25/2020 3:00 PM | 2/25/2020 6:00 PM

Можно ли написать запрос, который возвращает общее количество часов в задаче в день на основе значений времени начала и времени окончания? Что-то вроде:

Task | 2-21 | 2-22 | 2-23 | 2-24 | 2-25 | 2-26 | 2-27
A    |  0       0        0     1    | 1    0     0
B    |  0       0        0     2    | 3    0     0

Заранее спасибо!

Изменить: я планирую создать хранимую процедуру, в которой есть два входа, которые будут служить фиксированным диапазоном для данных (7-дневный диапазон) и будут автоматически вводить 0, если указанная дата недоступна в таблице.

-1
Joseph 24 Фев 2021 в 15:01

2 ответа

Лучший ответ

Если вам нужно перенести динамическое количество столбцов, вы должны проверить это статья. В нем рассказывается о различных методах и их эффективности. XML или динамический SQL - это, вероятно, то, что вы ищете.

select
  task,
  wdate = cast(start_time as date),
  total_hours = sum(datediff(HOUR, start_time, end_time))
into #t
from tasks
group by task, cast(start_time as date)


DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX);
SET @cols = STUFF((SELECT DISTINCT
                            ',' + QUOTENAME(c.[wdate])
                     FROM #t c FOR XML PATH(''), TYPE
                 ).value('.', 'nvarchar(max)'), 1, 1, '');
          
SET @query = 'SELECT
                [task], ' + @cols + '
              from (
                SELECT
                  [task],
                  [total_hours] AS [amount],
                  [wdate] AS [category]
                FROM #t
              ) x pivot (SUM(amount) for category in (' + @cols + ')) p';

EXECUTE (@query);
1
DerMaddi 24 Фев 2021 в 12:51

Если вы точно знаете, какие дни вам понадобятся в качестве столбцов, вы можете использовать сводную таблицу. Но если вы не знаете столбцы заранее, вам нужно будет использовать какой-то динамический SQL, как предложил Ларну.

Вот пример, если вы знали, что в вашем примере у вас было только 2 дня:

Этот синтаксис предназначен для Snowflake, но он похож на sql-server

select *
from (
         select
             task,
             date_trunc('day', start_time)                     day,
             datediff('hours', min(start_time), max(end_time)) diff
         from test_table
         group by task, day
         order by day
     )
         pivot (sum(diff) for day in ('2020-02-24', '2020-02-25')) as p
0
Simon Darr 24 Фев 2021 в 12:30