views:

158

answers:

3

Hi all, I need some help to build SQL Query. I have table having data like:

ID   Date         Value1 Value2 Code
1   12/01/2009     4       3.5     abc
2   12/02/2009     3       4.0     abc
3   11/03/2009     6       8.5     xyz
4   11/01/2009     2       5.5     abc
5   11/02/2009     4       6.0     xyz
6   12/03/2009     5       7.0     xyz

I need to show result something like...

        ---------
Code   | Data   |    November(Sum of Values in month)      December   Jan   Feb
abc    | Value1 |           2                                 7       0       0
       | Value2 |           5                                 7       0       0
xyz    | Value1 |           10                                5       0       0
       | Value2 |           14                                7       0       0
       ----------

I need sum of value in each month as in above data in columns group by code

Thanks
A: 

This isn't quite what you asked for because the number of columns is fixed, but I think it's a better way to what you want in SQL:

SELECT Code, 'Value1' As Data, MONTH(Date) AS Month, YEAR(Date) AS Year, SUM(Value1) AS Sum
FROM Table1
GROUP BY Code, MONTH(Date), YEAR(Date)
UNION ALL
SELECT Code, 'Value2' As Data, MONTH(Date) AS Month, YEAR(Date) AS Year, SUM(Value2) AS Sum
FROM Table1
GROUP BY Code, MONTH(Date), YEAR(Date)
ORDER BY Code, Data, Month, Year

Example output:

Code Data   Month   Year    Sum
abc  Value1 11  2009 2
abc  Value1 12  2009 7
abc  Value2 11  2009 5
abc  Value2 12  2009 7
xyz  Value1 11  2009 10
xyz  Value1 12  2009 5
xyz  Value2 11  2009 14
xyz  Value2 12  2009 7

I'd recommend that you use a bit of non-SQL code to reformat the result into exactly what you asked for before displaying it to the user rather than trying to return a variable number of columns in SQL.

Mark Byers
Thanks for your reply, I need to show month name as column and populate data like wise....
Muhammad Akhtar
I am using ASP.Net with SQL 2005
Muhammad Akhtar
Then it seems fine to me to return the results in the form I showed above and use some simple ASP.NET code to tranpose the results into the columns you want. I'm not sure what the best way of doing this in ASP.NET is, but you might be able to use something like a DataTable to collate the results. You could iterate over the result set and every time you see a month/year combination that you haven't seen before, create a new column in your DataTable for that. Then bind your DataTable to a GridView when you are done. I'm fairly sure that this is easier than trying to write it all in SQL.
Mark Byers
+2  A: 

Have a look at this solution, and let me know what you think.

You have to use both PIVOT and UNPIVOT in this instance to get the result you are looking for. Hope this helps.

DECLARE @Table TABLE(
        ID INT,
        Date DATETIME,
        Value1 INT,
        Value2 FLOAT,
        Code VARCHAR(10)
)

INSERT INTO @Table (ID,Date,Value1,Value2,Code) SELECT  1,'12/01/2009',4,3,'abc'
INSERT INTO @Table (ID,Date,Value1,Value2,Code) SELECT  2,'12/02/2009',3,4,'abc'
INSERT INTO @Table (ID,Date,Value1,Value2,Code) SELECT  3,'11/03/2009',6,8,'xyz'
INSERT INTO @Table (ID,Date,Value1,Value2,Code) SELECT  4,'11/01/2009',2,5,'abc'
INSERT INTO @Table (ID,Date,Value1,Value2,Code) SELECT  5,'11/02/2009',4,6,'xyz'
INSERT INTO @Table (ID,Date,Value1,Value2,Code) SELECT  6,'12/03/2009',5,7,'xyz'


;WITH UnPvt AS (
        SELECT  *
        FROM    (
                    SELECT  Code,
                            DATENAME(MM, Date) MonthNameVal,
                            SUM(Value1) Value1,
                            SUM(Value2) Value2
                    FROM    (
                                SELECT  Code,
                                        Date,
                                        CAST(Value1 AS FLOAT) Value1,
                                        Value2
                                FROM    @Table
                            ) v
                    GROUP BY    Code,
                                DATENAME(MM, Date)
                ) Sub
        UNPIVOT
                (
                    Vals FOR RowValues IN (Value1, Value2)
                ) AS UnPvt
)
SELECT  *
FROM    UnPvt
PIVOT   (
            SUM(Vals)
            FOR MonthNameVal IN ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November], [December])
        ) AS pvt
ORDER BY Code, RowValues

Have a look at

astander
No Doubt, you provide always greate solution, I love your solution. Thanks + 100000....... for you...... Again Thanks
Muhammad Akhtar
Solution is working perfectly; but could you plz give me somes links that will help me to understand the query; I mean pivot and unpivot used in the query.
Muhammad Akhtar
Have a look at the edited answer.
astander
I am getting this error; "The type of column "Value2" conflicts with the type of other columns specified in the UNPIVOT list" because both column have different datatype SUM(Value1) Value1, sum(Value2) Value2; like first have int and 2nd one have decimal/float
Muhammad Akhtar
I have Edit the value of value2 column; Thanks
Muhammad Akhtar
Changed the answer to CAST Value1 to Float. Have a look.
astander
Plz check my actual query in the below answer, I am still getting the same above error, Thanks
Muhammad Akhtar
See comment to your answer.
astander
Did you get it all fixed?
astander
yes.... Thanks alot
Muhammad Akhtar
Could you plz check my query again below in my posted answer, I am getting last error here when doing.. **Cast((sum(LastYearRevenue)/Sum(LastYearLets)) as Decimal(18,2)) LastYearADR**
Muhammad Akhtar
Getting same error The type of column "LastYearADR" conflicts with the type of other columns specified in the UNPIVOT list
Muhammad Akhtar
Problem is here just.. Cast((sum(LastYearRevenue)/Sum(LastYearLets)) as Decimal(18,2)) LastYearADR other than this every thing working perfectly. just plz check this. What's wrong here. I think I did right.... but.....
Muhammad Akhtar
Could you plz check now, I am in trouble right now, many thanks for your help; I have write some description in my query. thanks
Muhammad Akhtar
yes, you are right, that's done, I have pasted the final query in my answer at the end... Thanks alot... will not forget your help
Muhammad Akhtar
A: 

This is short query and hope you will understand...

WITH UnPvt AS ( 
    SELECT  * FROM    ( 
                SELECT  Code, 
                        DATENAME(MM, ForecastDate) MonthNameVal 
                        ,SUM(BOBLets) BOBLets/*int*/, SUM(BOBRevenue) BOBRevenue/*Decimal(18,2)*/,
                        Cast((sum(BOBRevenue)/sum(BOBLets)) as Decimal(18,2)) adr /*Need to calculate here*/
                FROM    ( 
                            SELECT  Code, ForecastDate 
                                    ,CAST(BOBLets AS Decimal(18,2)) BOBLets,BOBRevenue 
                            FROM    VW_DailyForecast
                        ) v 
                GROUP BY  Code, DATENAME(MM, ForecastDate) 
            ) Sub 
    UNPIVOT 
            ( 
                Vals FOR RowValues IN (BOBLets, BOBRevenue,adr) 
            ) AS UnPvt 
)
SELECT  * 
FROM    UnPvt 
PIVOT   ( 
            SUM(Vals) 
            FOR MonthNameVal IN ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November], [December]) 
        ) AS pvt 
ORDER BY Code, RowValues desc

Error: Error:The type of column "adr" conflicts with the type of other columns specified in the UNPIVOT list.

Simple Table Schema:

ForecastDate ---Datetime
BOBLets  --- int
BobRevenue --- Decimal
Code --- Varchar(20)

OK, I found the problem. The line CAST(SUM()/SUM() AS DECIMAL(18,2)) is different to the other sums.

Cast all you top values to DECIMAL(18,2)

Something like this

;WITH UnPvt AS ( 
    SELECT  * FROM    ( 
                SELECT  Code, 
                        DATENAME(MM, ForecastDate) MonthNameVal ,
                        CAST(SUM(LastYearLets) AS DECIMAL(18,2)) LastYearRooms, 
                        CAST(SUM(LastYearRevenue) AS DECIMAL(18,2)) LastYearRevenue,
                        CAST(SUM(LastYearRevenue)/SUM(LastYearLets) AS DECIMAL(18,2)) LastYearADR,
                        CAST(SUM(BudgetLets) AS DECIMAL(18,2)) BudgetLets, 
                        CAST(SUM(BudgetRevenue) AS DECIMAL(18,2)) BudgetRevenue,
                        CAST(SUM(FCastLets) AS DECIMAL(18,2)) FcastLets, 
                        CAST(SUM(FCastRevenue) AS DECIMAL(18,2)) FCastRevenue,
                        CAST(SUM(BOBLets) AS DECIMAL(18,2)) BOBLets, 
                        CAST(SUM(BOBRevenue) AS DECIMAL(18,2)) BOBRevenue
                FROM    ( 
                            SELECT  Code, 
                                    ForecastDate ,
                                    CAST(LastYearLets AS Decimal(18,2)) LastYearLets,
                                    CAST(LastYearRevenue AS DECIMAL(18,2)) LastYearRevenue,
                                    CAST(BudgetLets AS Decimal(18,2)) BudgetLets,
                                    BudgetRevenue ,
                                    CAST(FcastLets AS Decimal(18,2)) FcastLets,
                                    FCastRevenue ,
                                    CAST(BOBLets AS Decimal(18,2)) BOBLets,
                                    BOBRevenue 
                            FROM    VW_DailyForecast 
                            where   forecastYear=2009 
                            AND     hotelID=1 
                            AND     SegmentID=1 
                        ) v 
                GROUP BY    Code, 
                            DATENAME(MM, ForecastDate) 
            ) Sub 
    UNPIVOT 
            ( 
                Vals FOR RowValues IN (LastYearRooms,LastYearRevenue,LastYearADR,BudgetLets,BudgetRevenue,FcastLets,FCastRevenue,BOBLets, BOBRevenue) 
            ) AS UnPvt 
)

SELECT  * 
FROM    UnPvt 
PIVOT   ( 
            SUM(Vals) 
            FOR MonthNameVal IN ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November], [December]) 
        ) AS pvt 
ORDER BY Code, RowValues desc

Final Query

WITH UnPvt AS ( 
    SELECT  * FROM    ( 
                SELECT  Code, DATENAME(MM, ForecastDate) MonthNameVal 
                        ,CAST(SUM(LastYearLets) as decimal(18,2)) LastYearRooms ,CAST(SUM(LastYearRevenue) as Decimal(18,2)) LastYearRevenue
                        ,CAST((SUM(LastYearRevenue)/SUM(LastYearLets)) as decimal(18,2)) LastYearADR
                        ,CAST(SUM(BudgetLets) as Decimal(18,2)) BudgetRooms, CAST(SUM(BudgetRevenue) as decimal(18,2)) BudgetRevenue
                        ,CAST((SUM(BudgetRevenue)/SUM(BudgetLets)) as decimal(18,2)) BudgetADR
                        ,CAST(SUM(FCastLets)as decimal(18,2)) FcastRooms, CAST(SUM(FCastRevenue)as decimal(18,2)) FCastRevenue
                        ,CAST((SUM(FCastRevenue)/SUM(FCastLets)) as decimal(18,2)) FCastADR
                        ,CAST(SUM(BOBLets)as decimal(18,2)) BOBRooms, CAST(SUM(BOBRevenue)as decimal(18,2)) BOBRevenue
                        ,CAST((SUM(BOBRevenue)/SUM(BOBLets)) as decimal(18,2)) BOBADR
                FROM    ( 
                            SELECT  Code, ForecastDate 
                                    ,LastYearLets,LastYearRevenue ,LastYearADR,BudgetLets,BudgetRevenue, BudgetADR
                                    ,FcastLets,FCastRevenue, FCastADR, BOBLets, BOBRevenue, BOBADR
                            FROM    VW_DailyForecast where forecastYear=2009 AND hotelID=1 AND SegmentID=1 
                        ) v 
                GROUP BY    Code, 
                            DATENAME(MM, ForecastDate) 
            ) Sub 
    UNPIVOT 
            ( 
                Vals FOR RowValues IN (LastYearRooms,LastYearRevenue,LastYearADR,BudgetRooms,BudgetRevenue,BudgetADR,FcastRooms,FCastRevenue,FCastADR,BOBRooms, BOBRevenue,BOBADR) 
            ) AS UnPvt 
)
SELECT  * 
FROM    UnPvt 
PIVOT   ( 
            SUM(Vals) 
            FOR MonthNameVal IN ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November], [December]) 
        ) AS pvt 
ORDER BY Code, RowValues desc
Muhammad Akhtar
Change it to CAST(BOBLets AS DECIMAL(18,2)) not CAST(BOBLets AS DECIMAL)
astander
Please alos provide the table structure for me.
astander
Check the edit to your answer. I think that should work now.
astander
Let me know if that worked X-)
astander
yes, you are right, that's done, I have pasted the final query in my answer at the end... Thanks alot... will not forget your help.
Muhammad Akhtar
That would seem correct. The Unpivot requires that all the fields be of the same type...
astander