具有多个聚合的Dynamic Pivot SQL

时间:2018-09-24 08:15:19

标签: sql sql-server dynamic pivot

我有一个查询,可以查询动态的列列表(即列可以随时更改),并旋转显示这些列的Maximum InstalledDate的数据。但是我的问题是,如何进行多个聚合?我也需要每个PlaceRef都具有Max LocationCode,MakeCode和ModelCode,但是我很难做到这一点。预先非常感谢。

    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 :(得分:0)

我建议您不要在此处使用“数据透视”功能,而应使用采用“条件聚合”的较旧技术。这意味着“列”字符串的创建更为复杂,但确实允许您在单个查询中输出多个聚合。以下代码未经测试,因为没有可使用的示例数据:

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;