具有动态生成列的SQL查询

时间:2015-03-27 23:16:43

标签: sql pivot dynamic-sql

以上是我想要使用的一组示例数据。我如何构建一个动态返回以下列和行的查询。

我需要查询来生成一个表,该表包含每个分组年份和每个M1,M2,M3 ...列的列:

Simulation,Year2000M1,Year2000M2,Year2000M3,Year2000M4,Year2000M5,Year2001M1...
1,1,2,3,4,5,6...
2,26,27,28,29,30,31...
3,51,52,53,54,55,56...

我真的不知道从哪里开始。我以前从未在行中生成过列。

1 个答案:

答案 0 :(得分:1)

这是带有SQL Server的列动态版本(我不知道您使用的是哪个RDBMS)

DECLARE @Years NVARCHAR(4000)
SET @Years = ''

SELECT 
  @Years = COALESCE(CASE 
                      WHEN @Years = '' THEN 'Year' + CAST(Year AS NVARCHAR) + COLUMN_NAME  
                      ELSE @Years +', ' + 'Year' + CAST(Year AS NVARCHAR) + COLUMN_NAME  END, '')

FROM 
  INFORMATION_SCHEMA.COLUMNS
  CROSS JOIN (SELECT DISTINCT Year FROM Test) Years
WHERE 
  TABLE_NAME = 'Test' AND
  COLUMN_NAME LIKE 'M%'

DECLARE @Columns NVARCHAR(4000)
SET @Columns = ''
SELECT
  @Columns = COALESCE(CASE 
                      WHEN @Columns = '' THEN COLUMN_NAME 
                      ELSE @Columns +', ' + COLUMN_NAME END, '')
FROM 
  INFORMATION_SCHEMA.COLUMNS
WHERE 
  TABLE_NAME = 'Test' AND
  COLUMN_NAME LIKE 'M%'

DECLARE @Query NVARCHAR(MAX)

SET @Query = '
SELECT
  *
FROM
(
  SELECT 
    Simulation, (''Year'' + CAST(Year AS VARCHAR) + M) AS YearM, Value
  FROM
  (
  SELECT 
    Simulation, Year, M, Value
  FROM 
    (SELECT * FROM Test) p
  UNPIVOT
     (Value FOR M IN 
        (' + @Columns + ')
  ) AS unpvt) data
) Data1
PIVOT (
  MAX(Value) FOR YearM IN (' + @Years + ')) AS result'

EXECUTE(@Query)

这里有一个演示版 http://sqlfiddle.com/#!6/e7c99/49

这是解决问题的另一种方法,但是使用静态列(没有UNPIVOT / PIVOT)。

SELECT
  Simulation,
  SUM(CASE WHEN Year = 2000 THEN M1 ELSE 0 END) Year2000M1,
  SUM(CASE WHEN Year = 2000 THEN M2 ELSE 0 END) Year2000M2,
  SUM(CASE WHEN Year = 2000 THEN M3 ELSE 0 END) Year2000M3,
  SUM(CASE WHEN Year = 2000 THEN M4 ELSE 0 END) Year2000M4,
  SUM(CASE WHEN Year = 2000 THEN M5 ELSE 0 END) Year2000M5,
  SUM(CASE WHEN Year = 2001 THEN M1 ELSE 0 END) Year2001M1,
  SUM(CASE WHEN Year = 2001 THEN M2 ELSE 0 END) Year2001M2,
  SUM(CASE WHEN Year = 2001 THEN M3 ELSE 0 END) Year2001M3,
  SUM(CASE WHEN Year = 2001 THEN M4 ELSE 0 END) Year2001M4,
  SUM(CASE WHEN Year = 2001 THEN M5 ELSE 0 END) Year2001M5,
  SUM(CASE WHEN Year = 2002 THEN M1 ELSE 0 END) Year2002M1,
  SUM(CASE WHEN Year = 2002 THEN M2 ELSE 0 END) Year2002M2,
  SUM(CASE WHEN Year = 2002 THEN M3 ELSE 0 END) Year2002M3,
  SUM(CASE WHEN Year = 2002 THEN M4 ELSE 0 END) Year2002M4,
  SUM(CASE WHEN Year = 2002 THEN M5 ELSE 0 END) Year2002M5,
  SUM(CASE WHEN Year = 2003 THEN M1 ELSE 0 END) Year2003M1,
  SUM(CASE WHEN Year = 2003 THEN M2 ELSE 0 END) Year2003M2,
  SUM(CASE WHEN Year = 2003 THEN M3 ELSE 0 END) Year2003M3,
  SUM(CASE WHEN Year = 2003 THEN M4 ELSE 0 END) Year2003M4,
  SUM(CASE WHEN Year = 2003 THEN M5 ELSE 0 END) Year2003M5,
  SUM(CASE WHEN Year = 2004 THEN M1 ELSE 0 END) Year2004M1,
  SUM(CASE WHEN Year = 2004 THEN M2 ELSE 0 END) Year2004M2,
  SUM(CASE WHEN Year = 2004 THEN M3 ELSE 0 END) Year2004M3,
  SUM(CASE WHEN Year = 2004 THEN M4 ELSE 0 END) Year2004M4,
  SUM(CASE WHEN Year = 2004 THEN M5 ELSE 0 END) Year2004M5
FROM
  Test
GROUP BY 
  Simulation

这里有一个演示版 http://sqlfiddle.com/#!6/e7c99/18

这是解决问题的另一种方法,但是使用静态列(使用UNPIVOT / PIVOT)

SELECT
  *
FROM
(
  SELECT 
    Simulation, ('Year' + CAST(Year AS VARCHAR) + M) AS YearM, Value
  FROM
  (
  SELECT 
    Simulation, Year, M, Value
  FROM 
    (SELECT * FROM Test) p
  UNPIVOT
     (Value FOR M IN 
        (M1, M2, M3, M4, M5)
  ) AS unpvt) data
) Data1
PIVOT (
  MAX(Value) FOR YearM IN (
    Year2000M1,Year2000M2,Year2000M3,Year2000M4,Year2000M5,
    Year2001M1,Year2001M2,Year2001M3,Year2001M4,Year2001M5,
    Year2002M1,Year2002M2,Year2002M3,Year2002M4,Year2002M5,
    Year2003M1,Year2003M2,Year2003M3,Year2003M4,Year2003M5,
    Year2004M1,Year2004M2,Year2004M3,Year2004M4,Year2004M5)) AS result

这里有一个演示版 http://sqlfiddle.com/#!6/e7c99/17

希望这有帮助