Динамический сводный SQL с несколькими агрегациями - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть запрос, который просматривает динамический список столбцов (то есть столбцы могут измениться в любое время) и поворачивает данные, показывая максимальную установленную дату для этих столбцов.Мой вопрос, однако, как мне пройти через более чем одну агрегацию?Мне нужно иметь Max LocationCode, MakeCode и ModelCode для каждого PlaceRef, но я изо всех сил пытаюсь это сделать.Большое спасибо заранее.

    DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N', p.' + QUOTENAME(Component ) 
  FROM (SELECT p.Component FROM VwLocationComponentCurrent AS p
    INNER JOIN VwLocationListEntriesCurrent AS o ON p.PlaceRef = o.PlaceRef
    where o.LocationList = N'NEWBUILD'
    GROUP BY p.Component) AS x;



SET @sql = N'
SELECT PlaceRef, Address1, StreetName, PostCode, Substatus, BuildingType, BuildDate, ' + STUFF(@columns , 1, 2, '') + '
FROM
(
  SELECT 
  vwLocationCurrent.PlaceRef
  ,vwLocationCurrent.BuildDate
  ,vwLocationCurrent.SubStatus
  ,vwLocationCurrent.StreetName
  ,vwLocationCurrent.Address1
  ,vwLocationCurrent.Address2
  ,vwLocationCurrent.Address3
  ,vwLocationCurrent.PostCode
  ,VwLocationComponentCurrent.Component
  ,VwLocationComponentCurrent.SubLocationCode
  ,VwLocationComponentCurrent.InstalledDate
  ,VwLocationComponentCurrent.MakeCode
  ,VwLocationComponentCurrent.ModelCode
  ,VwLocationListEntriesCurrent.LocationList
  ,vwLocationCurrent.BuildingType

FROM
  vwLocationCurrent
  INNER JOIN VwLocationListEntriesCurrent
    ON vwLocationCurrent.PlaceRef = VwLocationListEntriesCurrent.PlaceRef
  LEFT OUTER JOIN VwLocationComponentCurrent
    ON vwLocationCurrent.PlaceRef = VwLocationComponentCurrent.PlaceRef
    WHERE
VwLocationListEntriesCurrent.LocationList = ''NEWBUILD''
) AS j

PIVOT
(
  MAX(InstalledDate) FOR Component IN ('
  + STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
  + ')
) AS p;'
;
PRINT @sql;
EXEC sp_executesql @sql;

1 Ответ

0 голосов
/ 24 сентября 2018

Я предлагаю вам не использовать здесь функцию "pivot", вместо этого используйте более старую технику, использующую "условные агрегаты".Это означает, что создание строки «столбцы» является более сложным, но оно позволяет вам выводить несколько агрегатов в одном запросе.Следующий код не протестирован, так как нет примеров данных для работы:

DECLARE @columns nvarchar(max)
      , @sql nvarchar(max);
SET @columns = N'';
SELECT
       @columns +=
     + N', max(case when Component = p.' + QUOTENAME(Component) + N' then SubLocationCode end) as ' + QUOTENAME('Loc_' + Component)
     + N', max(case when Component = p.' + QUOTENAME(Component) + N' then MakeCode end) as ' + QUOTENAME('Mak_' + Component)
     + N', max(case when Component = p.' + QUOTENAME(Component) + N' then ModelCode end) as '+  QUOTENAME('Mod_' + Component)
FROM (
    SELECT
        p.Component
    FROM VwLocationComponentCurrent AS p
    INNER JOIN VwLocationListEntriesCurrent AS o ON p.PlaceRef = o.PlaceRef
    WHERE o.LocationList = N'NEWBUILD'
    GROUP BY
        p.Component
) AS x;

SET @sql = N'
SELECT PlaceRef, Address1, StreetName, PostCode, SubStatus, BuildingType, BuildDate, ' + STUFF(@columns, 1, 2, '') + '
FROM
(
  SELECT 
   vwLocationCurrent.PlaceRef
  ,vwLocationCurrent.Address1
  ,vwLocationCurrent.StreetName
  ,vwLocationCurrent.PostCode
  ,vwLocationCurrent.SubStatus
  ,vwLocationCurrent.BuildingType
  ,vwLocationCurrent.BuildDate'
+ STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
+ N' FROM vwLocationCurrent
  INNER JOIN VwLocationListEntriesCurrent
    ON vwLocationCurrent.PlaceRef = VwLocationListEntriesCurrent.PlaceRef
  LEFT OUTER JOIN VwLocationComponentCurrent
    ON vwLocationCurrent.PlaceRef = VwLocationComponentCurrent.PlaceRef
  WHERE VwLocationListEntriesCurrent.LocationList = ''NEWBUILD''
  GROUP BY
   vwLocationCurrent.PlaceRef
  ,vwLocationCurrent.Address1
  ,vwLocationCurrent.StreetName
  ,vwLocationCurrent.PostCode
  ,vwLocationCurrent.SubStatus
  ,vwLocationCurrent.BuildingType
) AS p;'
;
PRINT @sql;
EXEC sp_executesql @sql;
...