How to manually set sort order of Unpivot and pivot in sql server

6ie5vjzr  于 12个月前  发布在  SQL Server
关注(0)|答案(4)|浏览(119)

Hi I have applied Unpivot and pivot to my data. All is going well excepts I want to arrange my output in the same order as specified in "IN" clause of unpivot. Please help. Here is what I have done so far:

CREATE TABLE #myTable
    (
    [ForYear] [smallint] NOT NULL,
    [ForMonth] [tinyint] NOT NULL,
    [TrainingDoneThisMonth] [bit] NULL,
    [FoodQualityStatus] [bit] NULL,
    [NoOfAllDrugTests] [int] NULL,
    [NoOfAllAlcoholTests] [int] NULL
    )

    INSERT INTO #myTable 
    values
    (2016,1,1,0,5,10),
    (2016,2,0,1,15,5),
    (2016,3,1,0,20,15),
    (2016,4,0,1,5,25),
    (2016,5,1,0,10,30),
    (2015,1,1,0,5,10),
    (2015,2,0,1,15,5),
    (2015,3,1,0,20,15),
    (2015,4,0,1,5,25),
    (2015,5,1,0,10,30)
select * from(SELECT *
    FROM (
        SELECT  DATENAME(month,DATEADD(month,[ForMonth]-1,'1970-01-01')) as d,
                CAST([TrainingDoneThisMonth] as int) as [TrainingDoneThisMonth],
                CAST([FoodQualityStatus] as int) as [FoodQualityStatus],
                [NoOfAllDrugTests],
                [NoOfAllAlcoholTests]

        FROM #myTable
        WHERE foryear=2016
        ) d
    UNPIVOT (
      [VALUES] FOR [Objective] in ([TrainingDoneThisMonth],[FoodQualityStatus],[NoOfAllDrugTests],[NoOfAllAlcoholTests])
    ) unpvt
) as p
PIVOT (
    SUM([VALUES]) FOR d IN ([January],[February],[March],[April],[May])
) as pvt

I need result in this order: [TrainingDoneThisMonth],[FoodQualityStatus],[NoOfAllDrugTests],[NoOfAllAlcoholTests]

I have tried : SQL Server , restrict UNPIVOT to order columns automatically but unable to make it working.

slhcrj9b

slhcrj9b1#

Try this:

CREATE TABLE #myTable
        (
        [ForYear] [smallint] NOT NULL,
        [ForMonth] [tinyint] NOT NULL,
        [TrainingDoneThisMonth] [bit] NULL,
        [FoodQualityStatus] [bit] NULL,
        [NoOfAllDrugTests] [int] NULL,
        [NoOfAllAlcoholTests] [int] NULL
        )

        INSERT INTO #myTable 
        values
        (2016,1,1,0,5,10),
        (2016,2,0,1,15,5),
        (2016,3,1,0,20,15),
        (2016,4,0,1,5,25),
        (2016,5,1,0,10,30),
        (2015,1,1,0,5,10),
        (2015,2,0,1,15,5),
        (2015,3,1,0,20,15),
        (2015,4,0,1,5,25),
        (2015,5,1,0,10,30)
    select *, 
          CASE WHEN objective = 'TrainingDoneThisMonth' THEN 1 
               WHEN objective = 'FoodQualityStatus' THEN 2 
               WHEN objective = 'NoOfAllDrugTests' THEN 3 
               WHEN objective = 'NoOfallAlcoholTests' THEN 4 
           ELSE 5 END AS [ranking]
 from(SELECT *
        FROM (
            SELECT  DATENAME(month,DATEADD(month,[ForMonth]-1,'1970-01-01')) as d,
                    CAST([TrainingDoneThisMonth] as int) as [TrainingDoneThisMonth],
                    CAST([FoodQualityStatus] as int) as [FoodQualityStatus],
                    [NoOfAllDrugTests],
                    [NoOfAllAlcoholTests]

            FROM #myTable
            WHERE foryear=2016
            ) d
        UNPIVOT (
          [VALUES] FOR [Objective] in ([TrainingDoneThisMonth],[FoodQualityStatus],[NoOfAllDrugTests],[NoOfAllAlcoholTests])
    ) unpvt
) as p
PIVOT (
    SUM([VALUES]) FOR d IN ([January],[February],[March],[April],[May])
) as pvt
ORDER BY ranking 
DROP TABLE #myTable
bxjv4tth

bxjv4tth2#

create table #objective
              (obj varchar(100),ord int)

    insert into #objective (obj,ord) values('TrainingDoneThisMonth',1)
    insert into #objective (obj,ord) values('FoodQualityStatus',2)

    insert into #objective (obj,ord) values('NoOfAllDrugTests',3)
`  `insert into #objective (obj,ord) values('NoOfAllDrugTests',4)

CREATE TABLE #myTable
        (
        [ForYear] [smallint] NOT NULL,
        [ForMonth] [tinyint] NOT NULL,
        [TrainingDoneThisMonth] [bit] NULL,
        [FoodQualityStatus] [bit] NULL,
        [NoOfAllDrugTests] [int] NULL,
        [NoOfAllAlcoholTests] [int] NULL
        )

        INSERT INTO #myTable 
        values
        (2016,1,1,0,5,10),
        (2016,2,0,1,15,5),
        (2016,3,1,0,20,15),
        (2016,4,0,1,5,25),
        (2016,5,1,0,10,30),
        (2015,1,1,0,5,10),
        (2015,2,0,1,15,5),
        (2015,3,1,0,20,15),
        (2015,4,0,1,5,25),
        (2015,5,1,0,10,30)
    select * into #ajay
    --, 
    --      CASE WHEN objective = 'TrainingDoneThisMonth' THEN 1 
    --           WHEN objective = 'FoodQualityStatus' THEN 2 
    --           WHEN objective = 'NoOfAllDrugTests' THEN 3 
    --           WHEN objective = 'NoOfallAlcoholTests' THEN 4 
    --       ELSE 5 END AS [ranking]
 from(SELECT *
        FROM (
            SELECT  DATENAME(month,DATEADD(month,[ForMonth]-1,'1970-01-01')) as d,
                    CAST([TrainingDoneThisMonth] as int) as [TrainingDoneThisMonth],
                    CAST([FoodQualityStatus] as int) as [FoodQualityStatus],
                    [NoOfAllDrugTests],
                    [NoOfAllAlcoholTests]

            FROM #myTable
            WHERE foryear=2016
            ) d
        UNPIVOT (
          [VALUES] FOR [Objective] in ([TrainingDoneThisMonth],[FoodQualityStatus],[NoOfAllDrugTests],[NoOfAllAlcoholTests])
    ) unpvt
) as p
PIVOT (
    SUM([VALUES]) FOR d IN ([January],[February],[March],[April],[May])
) as pvt
--ORDER BY ranking 

select #ajay.*,ord from #ajay
join objective on objective.obj=#ajay.[Objective]
order by ord
DROP TABLE #myTable
DROP TABLE #ajay
qyswt5oh

qyswt5oh3#

I had the same need after importing a series of Excel Worksheet containing a varying number of Columns and needing to unpivot them into a linear dataset.

I used the column_id to set the sequence after joining to the tempdb.sys.columns.

DROP TABLE IF EXISTS #SPLOAD    
go
    SELECT  * 
    INTO #SPLOAD
    FROM OPENROWSET(
        'Microsoft.ACE.OLEDB.16.0','Excel 12.0;HDR=YES;Database=C:\ESPClientUpload\OR_BakerCitySchoolDistrict\ERPLoading\Classified XXXX Salary Schedule.xlsx',
        'SELECT * FROM [sheet1$]') AS A
go

--Dynamic SQL created from a template and discovery of the pivot columns using tempdb.sys.columns
SELECT
     24                                         AS [PlanSequence]
    ,N'Classified - OSEA'                       AS [Plan]
    ,DENSE_RANK() OVER(ORDER BY C.[Seq])        AS [GradeSequence]
    --THis gobbledegook restores the '.' (decimal point)  the Ace Driver converted to a '#' 
    ,CASE
        WHEN CHARINDEX(N':',[Grade])<=0 THEN [Grade]
        WHEN CHARINDEX(N'#',[Grade])>CHARINDEX(N':',[Grade]) THEN REPLACE([Grade],N'#',N'.')
        ELSE [Grade]
    END                                         AS [Grade]
    ,[Row]                                      AS [StepSequence]
    ,[Step]
    ,[Amount]
    ,0 AS [IsPivot]
FROM (SELECT 
         [Classified - XXXX]    AS [Step]
        ,ROW_NUMBER() OVER(ORDER BY  getdate()) As [Row]
        ,[Range 1: 8#0 ]
        ,[Range 1: 8#5]
        ,[Range 1: 9#0]
        ,[Range 2: 8#0]
        ,[Range 2: 8#5]
        ,[Range 2: 9#0]
        ,[Range 3: 8#0]
        ,[Range 3: 9#0]
        ,[Range 4]
        ,[Night Shift Differential]
 
    FROM #SPLOAD) AS P
UNPIVOT 
    ([Amount] FOR [Grade] IN (
        [Range 1: 8#0 ]
        ,[Range 1: 8#5]
        ,[Range 1: 9#0]
        ,[Range 2: 8#0]
        ,[Range 2: 8#5]
        ,[Range 2: 9#0]
        ,[Range 3: 8#0]
        ,[Range 3: 9#0]
        ,[Range 4]
        ,[Night Shift Differential]
        )
    ) AS A
--**** Heres the Magic ***
INNER JOIN (SELECT [name],[column_id] AS [Seq]
            FROM tempdb.sys.columns
            WHERE  object_id = Object_id('tempdb..#SPLOAD')) AS C
ON C.[name]=A.[Grade]
lymnna71

lymnna714#

You can try this option:

ORDER BY piv.region, (CASE ID 
                                    WHEN '1' THEN 1 
                                    WHEN '2' THEN 2
                                    WHEN '3' THEN 3 
                                    WHEN '4' THEN 4
                                    WHEN '5' THEN 5 
                                    END) ASC

Full query on github

相关问题