19
TRANSFORM Avg(CASE WHEN [temp].[sumUnits] > 0 
                   THEN [temp].[SumAvgRent] / [temp].[sumUnits] 
                   ELSE 0 
              END) AS Expr1
SELECT [temp].[Description]
  FROM [temp] 
GROUP BY [temp].[Description]
PIVOT [temp].[Period];

Need to convert this query for sql server

I have read all other posts but unable to convert this into the same

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Vipin Jain
  • 1,382
  • 1
  • 10
  • 19
  • Can you please explain what are you trying to do with some sample data and the desired output? – Mahmoud Gamal Dec 19 '12 at 13:12
  • @MahmoudGamal : Dont know its just some query written in ms access. and we have to convert the program into php application with sql server 2005! – Vipin Jain Dec 19 '12 at 13:14

1 Answers1

22

Here is the equivalent version using the PIVOT table operator:

SELECT *
FROM
(
  SELECT 
    CASE 
      WHEN sumUnits > 0 
      THEN SumAvgRent / sumUnits ELSE 0 
  END AS Expr1,
  Description,
  Period
  FROM temp
) t
PIVOT
(
  AVG(Expr1)
  FOR Period IN(Period1, Period2, Period3)
) p;

SQL Fiddle Demo

For instance, this will give you:

| DESCRIPTION | PERIOD1 | PERIOD2 | PERIOD3 |
---------------------------------------------
|          D1 |      10 |       0 |      20 |
|          D2 |     100 |    1000 |       0 |
|          D3 |      50 |      10 |       2 |

Note that When using the MS SQL Server PIVOT table operator, you have to enter the values for the pivoted column. However, IN MS Access, This was the work that TRANSFORM with PIVOT do, which is getting the values of the pivoted column dynamically. In this case you have to do this dynamically with the PIVOT operator, like so:

DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);

SELECT @cols = STUFF((SELECT distinct 
                        ',' +
                        QUOTENAME(Period)
                FROM temp
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');



SET @query =  ' SELECT Description, ' + @cols + '
    FROM 
    (
      SELECT 
        CASE 
          WHEN sumUnits > 0 
          THEN SumAvgRent / sumUnits ELSE 0 
      END AS Expr1,
      Description,
      Period
      FROM temp
    ) t
    PIVOT
    (
      AVG(Expr1)
      FOR Period IN( ' + @cols + ') 
    ) p ';



Execute(@query);

Updated SQL Fiddle Demo

This should give you the same result:

| DESCRIPTION | PERIOD1 | PERIOD2 | PERIOD3 |
---------------------------------------------
|          D1 |      10 |       0 |      20 |
|          D2 |     100 |    1000 |       0 |
|          D3 |      50 |      10 |       2 |
Mahmoud Gamal
  • 78,257
  • 17
  • 139
  • 164
  • Thanks for the response now i get a clear view of what to do with the query. let me do the same and check wether it works the same way or not :) – Vipin Jain Dec 20 '12 at 07:02
  • Thank you Mahmoud. How would you write this into a CREATE VIEW statement? – Kopernik Dec 12 '13 at 17:08
  • 1
    @avguchenko - AFAIK, you can't write this into a view nor a UDF, because of the dynamic sql, but you can however do it inside a stored procedure, it will work fine. – Mahmoud Gamal Dec 13 '13 at 03:05
  • Just a minor update _without_ using XML: [SQL fiddle](http://www.sqlfiddle.com/#!18/f0306/66) – Jinxed Aug 08 '18 at 13:45