垂直显示sql server 2005的水平行

时间:2012-02-29 14:01:47

标签: sql-server-2005 tsql

当我发出像

这样的选择语句时
SELECT EMPID,ENAME,SALARY,DEPARTMENT from EMPLOYEE

然后数据显示

EMPID     ENAME    SALARY   DEPARTMENT
---------------------------------------------
01        TEST1    2000     A/C
02        TEST2    3000     SALES

但现在我想表现出像

EMPID       01      02

ENAME       TEST1   TEST2

SALARY      2000    3000

DEPARTMENT  A/C     SALES

所以如何为上面的查询编写sql。

2 个答案:

答案 0 :(得分:1)

也许是这样的:

首先是一些测试数据:

CREATE TABLE tblTempValues
    (
        EMPID VARCHAR(100), 
        ENAME VARCHAR(100),
        SALARY INT, 
        DEPARTMENT VARCHAR(100)
    )

INSERT INTO tblTempValues
VALUES
    ('01','TEST1',2000,'A/C'),
    ('02','TEST2',3000,'SALES')

将列添加到PIVOT。我在ROW_NUMBER上使用EMPID

DECLARE @cols VARCHAR(MAX)
;WITH CTE
AS
(
    SELECT
        ROW_NUMBER() OVER(ORDER BY tblTempValues.EMPID) AS RowNbr
    FROM
        tblTempValues
)
SELECT
    @cols=COALESCE(@cols +','+QUOTENAME(RowNbr),QUOTENAME(RowNbr))
FROM
    CTE

然后像这样做一个动态的角色。 orderWeight以便您拥有列的顺序:

DECLARE @query NVARCHAR(4000)=
N';WITH CTE
AS
(
    SELECT ''EMPID'' AS ID, CAST(EMPID AS VARCHAR(MAX)) AS Value, ROW_NUMBER() OVER(ORDER BY EMPID) AS RowId,1 as orderWeight FROM tblTempValues UNION ALL
    SELECT ''ENAME'' AS ID, CAST(ENAME AS VARCHAR(MAX)) AS Value, ROW_NUMBER() OVER(ORDER BY EMPID) AS RowId,2 as orderWeight FROM tblTempValues UNION ALL
    SELECT ''SALARY'' AS ID, CAST(SALARY AS VARCHAR(MAX)) AS Value, ROW_NUMBER() OVER(ORDER BY EMPID) AS RowId,3 as orderWeight FROM tblTempValues UNION ALL
    SELECT ''DEPARTMENT'' AS ID, CAST(DEPARTMENT AS VARCHAR(MAX)) AS Value, ROW_NUMBER() OVER(ORDER BY EMPID) AS RowId,4 as orderWeight FROM tblTempValues
)
SELECT
    ID,'+@cols+'
FROM
    CTE
PIVOT
(
    MAX(Value)
    FOR RowId IN('+@cols+')

) AS p'

EXECUTE(@query)

然后在我的情况下,我将删除临时表

DROP TABLE tblTempValues

答案 1 :(得分:0)

首先关闭,“Rows to columns”问题一直出现,我通常会推荐一个PIVOT(),但在这种情况下,你将会有不同数量的“列”。你创造了新员工。所以我不知道如何使用PIVOT()。我能想到的唯一方法是采用基于clunky迭代的SQL。

这个答案违背了我更好的判断,如果你有大量的员工,我的表现会非常糟糕(我不能强调这一点!) - 但是计划在高峰期,或者1次报告等,它可能已经足够,具体取决于您的情况。

--#### Create Dummy Data
CREATE TABLE [dbo].[tbl_ExampleData](
    [EMPID] [varchar](2) NULL,
    [ENAME] [varchar](50) NULL,
    [SALARY] [decimal](18, 0) NULL,
    [DEPARTMENT] [varchar](50) NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[tbl_ExampleData] ([EMPID], [ENAME], [SALARY], [DEPARTMENT]) VALUES (N'01', N'TEST1', CAST(2000 AS Decimal(18, 0)), N'A/C')
GO
INSERT [dbo].[tbl_ExampleData] ([EMPID], [ENAME], [SALARY], [DEPARTMENT]) VALUES (N'02', N'TEST2', CAST(3000 AS Decimal(18, 0)), N'SALES')
GO

--#### Select data as columns
DECLARE @CrossTabCursor CURSOR
DECLARE @CursorVal_EmpID VARCHAR(4)

-- #### Create the Basic Temp Table that we will build the crosstab data in
CREATE TABLE #tbl_CrossTabExample ( [-] VARCHAR(50) )

-- #### Populate the Y axis
INSERT  INTO #tbl_CrossTabExample
        ( [-]

        )
        SELECT  'EMPID'
        UNION ALL
        SELECT  'ENAME'
        UNION ALL
        SELECT  'SALARY'
        UNION ALL
        SELECT  'DEPARTMENT'


-- #### Add the nessasary columns - in this case, a varchar column per employee
SET 
@CrossTabCursor = CURSOR FAST_FORWARD FOR
SELECT [EMPID] FROM [dbo].[tbl_ExampleData]
OPEN @CrossTabCursor
FETCH NEXT FROM @CrossTabCursor
        INTO @CursorVal_EmpID
WHILE @@FETCH_STATUS = 0 
    BEGIN 
        -- #### Add column to the new table query based on the current cursor position (branch number)
        EXEC ('ALTER TABLE #tbl_CrossTabExample ADD [' + @CursorVal_EmpID + '] VARCHAR(50) NULL')

        -- #### Populate the new employee column
       EXEC ('UPDATE #tbl_CrossTabExample SET [' + @CursorVal_EmpID + '] = (SELECT EMPID FROM [tbl_ExampleData] B WHERE B.EMPID = ''' + @CursorVal_EmpID + ''') WHERE #tbl_CrossTabExample.[-] = ''EMPID''')
       EXEC ('UPDATE #tbl_CrossTabExample SET [' + @CursorVal_EmpID + '] = (SELECT ENAME FROM [tbl_ExampleData] B WHERE B.EMPID = ''' + @CursorVal_EmpID + ''') WHERE #tbl_CrossTabExample.[-] = ''ENAME''')
       EXEC ('UPDATE #tbl_CrossTabExample SET [' + @CursorVal_EmpID + '] = (SELECT SALARY FROM [tbl_ExampleData] B WHERE B.EMPID = ''' + @CursorVal_EmpID + ''') WHERE #tbl_CrossTabExample.[-] = ''SALARY''')
       EXEC ('UPDATE #tbl_CrossTabExample SET [' + @CursorVal_EmpID + '] = (SELECT DEPARTMENT FROM [tbl_ExampleData] B WHERE B.EMPID = ''' + @CursorVal_EmpID + ''') WHERE #tbl_CrossTabExample.[-] = ''DEPARTMENT''')

        -- #### move onto next branch
        FETCH NEXT FROM @CrossTabCursor 
                INTO @CursorVal_EmpID
    END 
CLOSE @CrossTabCursor 
DEALLOCATE @CrossTabCursor


-- #### Select the completed cross tab data
SELECT  *
FROM    #tbl_CrossTabExample

-- #### Drop the Temp Table
DROP TABLE #tbl_CrossTabExample

这个答案是一个非常粗略的概念证明,例如,你可以使用类似的逻辑动态构建一个PIVOT命令,它会更好地执行。