显示具有不同值(和空值)的相同列

时间:2014-11-18 16:29:02

标签: sql sql-server excel

我对SQL很新,我遇到了这个问题。

CREATE TABLE #TempTable
(WeekNr int,
Name varchar(30),
Value int)

INSERT INTO #TempTable VALUES (21,'John',100)
INSERT INTO #TempTable VALUES (21,'Michael',133)
INSERT INTO #TempTable VALUES (21,'Tony',50)
INSERT INTO #TempTable VALUES (22,'John',80)
INSERT INTO #TempTable VALUES (23,'Michael',188)
INSERT INTO #TempTable VALUES (23,'Tony',230)

表格显示了这种方式:

  WeekNr         Name        Value
  21             John        100
  21             Michael     133
  21             Tony        50
  22             John        80
  23             Michael     188
  23             Tony        230

我需要以这种方式安排数据:

  Name           Vale          Name         Value        Name        Value
  John           100           John          80          Michael     188
  Michael        133                                     Tony        230
  Tony           50

其中前两列引用WeekNr为21,第二列为WeekNr为22,然后WeekNr为23。

如果不包含任何WeekNr,将包含Null值会更好。例如,如果我做了类似

的事情
  DELETE FROM #TempTable WHERE WeekNr = 22

应该看起来像:

  Name           Vale          Name         Value        Name        Value
  John           100                                     Michael     188
  Michael        133                                     Tony        230
  Tony           50

因此可以轻松将数据导出到Excel。 我需要使用PIVOT还是UNPIVOT?

3 个答案:

答案 0 :(得分:3)

试试这个。

SELECT Max([21]) NAME,Max([id21]) Value,Max([22]) Name,Max([id22]) Value,Max([23]) Name,Max([id23]) Value
FROM   (SELECT Row_number()OVER(partition BY WeekNr ORDER BY NAME) rn,
               NAME,value,WeekNr,
               'id' + CONVERT(VARCHAR, WeekNr)      AS weeks
        FROM   #TempTable) a
       PIVOT (Max(NAME)
             FOR WeekNr IN ([21],[22],[23])) piv 
       PIVOT (max(value) 
             FOR weeks IN ([id21],[id22],[id23])) piv1
GROUP BY rn

如果您希望代码动态运行,请尝试此操作。

DECLARE @cols     VARCHAR(max)='',
        @cols1    VARCHAR(max)='',
        @aggcols  VARCHAR(max)='',
        @aggcols1 VARCHAR(max)='',
        @sql      NVARCHAR(max)

SELECT @cols += ',[' + CONVERT(VARCHAR(30), weeknr)+']',
       @cols1 += ',[id' + CONVERT(VARCHAR(30), weeknr)+']',
       @aggcols += ',max([' + CONVERT(VARCHAR(30), weeknr)+ ']) Name',
       @aggcols1 += ',max([id' + CONVERT(VARCHAR(30), weeknr)+ ']) Value'
FROM   (SELECT DISTINCT WeekNr
        FROM   #TempTable) A 

select @cols= RIGHT(@cols,len(@cols)-1)
select @cols1= RIGHT(@cols1,len(@cols1)-1)

select @aggcols= RIGHT(@aggcols,len(@aggcols)-1)
select @aggcols1= RIGHT(@aggcols1,len(@aggcols1)-1)

set @sql ='SELECT '+@aggcols+','+@aggcols1+'
FROM   (SELECT Row_number()OVER(partition BY WeekNr ORDER BY NAME) rn,
               NAME,value,WeekNr,
               ''id'' + CONVERT(VARCHAR, WeekNr)      AS weeks
        FROM   #TempTable) a
       PIVOT (Max(NAME)
             FOR WeekNr IN ('+@cols+')) piv 
       PIVOT (max(value) 
             FOR weeks IN ('+@cols1+')) piv1
GROUP BY rn'


exec sp_executesql @sql

答案 1 :(得分:1)

这不是你应该用SQL做的事情。 不要使用SQL ,开发和维护会很复杂。

SQL可以帮助您检索数据,您可以做某种演示文稿,但只要它变得过于复杂,您就会知道自己的方法是错误的。 您应该在前端应用程序中进行此类演示

答案 2 :(得分:0)

我也不是SQL Server的专家,事实上,我是一个相当新的人。我不认为这可以通过任何简单的方式实现。我能想到的最好的事情是运行三个不同的查询,你会有一个Where条件说明这样的事情:

SELECT Name, Value
FROM #TempTable
WHERE WeekNr = 21
GO

SELECT Name, Value
FROM #TempTable
WHERE WeekNr = 22
GO

SELECT Name, Value
FROM #TempTable
WHERE WeekNr = 23
GO

然后,当您运行整个查询时,它会为您提供三个数据窗口,但不会按照您希望的方式进行组织。问题是,如果你有数百或数千个WeekNr值,这几乎不可能以这种方式实现和运行。