Как переставить таблицу и сгруппировать результаты? - PullRequest
3 голосов
/ 26 мая 2020

У меня есть такая таблица:

datetime                   datacenter   machines
---------------------------------------------------------
2020-05-13 12:00:00.000    DC01         500
2020-05-13 12:00:00.000    DC02         100  
2020-04-10 13:00:00.000    DC01         510
2020-04-10 13:00:00.000    DC02         120
2020-03-1 14:00:00.000     DC01         530
2020-03-1 14:00:00.000     DC02         140

Столбец datetime имеет тип Datetime2, остальные - VARCHAR. Мне нужно создать новое представление, которое будет группировать записи по дате и времени и создавать столбцы из строк, которые имеют центры обработки данных dc01 и dc02, и помещать номер. машин в соответствующих строках, по существу транспонируя и объединяя данные.

В исходной таблице всегда будет 2 записи для каждого datetime, по одной для каждого центра обработки данных, и при объединении datetime должно быть уникальным. Вот для иллюстрации полученного view:

resulting_view

datetime                   dc01_machines   dc02_machines
---------------------------------------------------------
2020-05-13 12:00:00.000    500             100 
2020-04-10 13:00:00.000    510             120
2020-03-1 14:00:00.000     530             140

Я потратил некоторое время, пытаясь найти решения. На мой взгляд, у меня есть решение, которое состоит в том, чтобы сделать 2 отдельных выбора, по одному для каждого центра обработки данных, объединить их с помощью UNION, а затем просто сгруппировать их по дате и времени, но я уверен, что это ужасно, и он даже не работает, есть ошибка около invalid syntax near GROUP. Вот попытка:

(SELECT t1.datetime
 ,t1.machines as dc01_machines
 ,'' as dc02_machines
FROM table1 t1
WHERE datacenter = 'DC01')
UNION
 (SELECT t1.datetime
 ,'' as dc01_machines
 ,t1.machines as dc02_machines
FROM table1 t1
WHERE datacenter = 'DC02')
GROUP BY datetime

Спасибо, любая помощь приветствуется!

Ответы [ 2 ]

2 голосов
/ 26 мая 2020

Я бы порекомендовал условное агрегирование.

В отличие от синтаксиса, определяемого поставщиком c pivot, это переносимый подход (ie он работает в большинстве баз данных), который обычно работает как минимум так же или лучше, как указано производителем c реализация.

Он также более гибкий - это не имеет значения для вашего конкретного c варианта использования, но будет работать в более сложных случаях, которые pivot не может вместить (например: список машин из DC01 чей идентификатор 510 или больше, и машины из DC02 с идентификатором 120 или меньше).

select 
    datetime,
    max(case when datacenter = 'DC01' then machines end) dc01_machines,
    max(case when datacenter = 'DC02' then machines end) dc02_machines
from mytable
group by datetime
order by datetime
2 голосов
/ 26 мая 2020
CREATE TABLE yourtable ([datetime] datetime, datacenter varchar(10),machines INT)
insert into yourtable ([datetime],datacenter,machines) VALUES 
('2020-05-13 12:00:00.000' ,   'DC01'   ,  500 ),
('2020-05-13 12:00:00.000' ,   'DC02'   ,     100  ),
('2020-04-10 13:00:00.000',    'DC01'    ,     510),
('2020-04-10 13:00:00.000',    'DC02'    ,     120),
('2020-03-1 14:00:00.000',     'DC01'   ,      530),
('2020-03-1 14:00:00.000',     'DC02'   ,      140)
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.datacenter) 
            FROM yourtable c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT [datetime], ' + @cols + ' from 
            (
                select [datetime],datacenter,machines
                from yourtable
           ) x
            pivot 
            (
                 max(machines)
                for datacenter in (' + @cols + ')
            ) p '


execute(@query)
datetime                | DC01 | DC02
:---------------------- | ---: | ---:
2020-03-01 14:00:00.000 |  530 |  140
2020-04-10 13:00:00.000 |  510 |  120
2020-05-13 12:00:00.000 |  500 |  100

db <> fiddle здесь

...