Need Help in SQL Pivot Query

  • Hi,

    I have a SQL Table in the below structure and am trying to write a PIVOT Query to get the %contribution of Service Request Numbers by Warranty Type. Could anyone pls suggest how do i obtain this?

    SR_CountFWEEKprod_DESCWarrantyStatusOrders

    1201402XPS Desktops IW1

    1201402OptiPlex Desktops IWNULL

    1201402Other Electronics IWNULL

    3201402Personal Notebooks IW3

    6201402XPS Desktops OOWNULL

    1201402Imaging IWNULL

    5201402Tablets IWNULL

    18201402XPS Desktops UnknownNULL

    10201402Personal Desktops OOWNULL

    221201402XPS Desktops IWNULL

    Pivot Query that i have written is as below:

    SELECT * FROM

    ( SELECT COUNT( [SERVICE REQUEST NUMBER]) SR_Count, FWEEK, prod_DESC,

    [WarrantyStatus], SUM([ordercount]) AS Orders

    FROM [dbo].[GM_Logs_Wk05] where fweek = '201402'

    GROUP BY FWEEK, prod_DESC, [WarrantyStatus],[ordercount]

    ) AS A

    PIVOT

    (

    sum([SR_Count]) FOR [WarrantyStatus] in

    ([IW], [OOW]

    )

    )as b

    Output of the above pivot query is as below:

    FWEEKprod_DESCOrdersIWOOW

    201402Personal DesktopsNULL35810

    201402Imaging NULL1NULL

    201402XPS Desktops11NULL

    201402OptiPlex DesktopsNULL1NULL

    201402Other ElectronicsNULL1NULL

    201402Personal NotebooksNULL132445

    201402Tablets NULL5NULL

    201402Personal Notebooks 33NULL

    201402Personal Notebooks 1NULLNULL

    201402XPS NotebooksNULL23115

    201402XPS DesktopsNULL2216

    Help I need:

    1.How do I get just one row for one product (as for ex: Personal Notebooks is appearing 3times in the above output)

    2.Instead of getting the count – is it possible to get % of the column total as in if I draw a pivot on excel below is the output – just wondering how do I convert the value for count to % of total of the respective column

    Below is the excel output..(which I do in the excel pivot value field settings – show value as % of column total) which is the similar output i want thru a SQL Pivot query or any other means to acheive this in PIVOT...this query output is what am finally intending to use as a dataset in my SSRS Report.

    Prod_descIWOOW

    Personal Notebooks61.76%57.69%

    Personal Desktops16.67%12.82%

    XPS Notebooks10.78%19.23%

    XPS Desktops10.36%7.69%

    Tablets 0.23%0.00%

    Other Electronics0.05%0.00%

    OptiPlex Desktops0.05%0.00%

    Imaging 0.05%0.00%

    Grand Total100.00%100.00%

    Please help.

    thanks

  • please read this post (http://www.sqlservercentral.com/articles/SQLServerCentral/66909/) and then reply to this thread with a create table statement, insert statements with your sample data and then formatted output of the desired output. Then we can help you get what you want for this request.

    Best,
    Kevin G. Boles
    SQL Server Consultant
    SQL MVP 2007-2012
    TheSQLGuru on googles mail service

  • Hello,

    Thanks for sharing the URL which helps understand how to post the question.

    I have rewrriten the question in a word document and has been attached as an attachment name pivotquery.docx

    Please review and hope you help find me a solution.

    Regards

  • Please put the stuff up as a TEXT document. I don't download files that can run code. :hehe:

    Best,
    Kevin G. Boles
    SQL Server Consultant
    SQL MVP 2007-2012
    TheSQLGuru on googles mail service

  • geetha.jasmine (4/6/2013)


    Hello,

    Thanks for sharing the URL which helps understand how to post the question.

    I have rewrriten the question in a word document and has been attached as an attachment name pivotquery.docx

    Please review and hope you help find me a solution.

    Regards

    a word document is not what is required...please reread the URL posted.

    that said...does the following code give you some ideas...

    SELECT FWEEK, prod_DESC,

    cast (100 * SUM(CASE WHEN WarrantyStatus = 'IW' THEN orders ELSE 0 END) / SUM(Orders) as decimal(9,2)) as IWpercent,

    cast (100 * SUM(CASE WHEN WarrantyStatus = 'OOW' THEN orders ELSE 0 END) / SUM(Orders) as decimal(9,2)) as OOWpercent,

    cast (SUM(CASE WHEN WarrantyStatus = 'IW' THEN orders ELSE 0 END) as INT) AS IW,

    cast (SUM(CASE WHEN WarrantyStatus = 'OOW' THEN orders ELSE 0 END) as INT) AS OOW

    FROM gm_table

    GROUP BY FWEEK, prod_DESC

    HAVING (FWEEK = 201404)

    ________________________________________________________________
    you can lead a user to data....but you cannot make them think
    and remember....every day is a school day

  • TheSQLGuru (4/6/2013)


    Please put the stuff up as a TEXT document. I don't download files that can run code. :hehe:

    Word's .docx files cannot run code, as far as I know - that's what .docm files are for.

    The absence of evidence is not evidence of absence.
    Martin Rees

    You can lead a horse to water, but a pencil must be lead.
    Stan Laurel

  • Phil Parkin (4/7/2013)


    TheSQLGuru (4/6/2013)


    Please put the stuff up as a TEXT document. I don't download files that can run code. :hehe:

    Word's .docx files cannot run code, as far as I know - that's what .docm files are for.

    Learn all kinds of things on SSC.com!!

    Best,
    Kevin G. Boles
    SQL Server Consultant
    SQL MVP 2007-2012
    TheSQLGuru on googles mail service

  • Hi geetha jasmine,

    I would not use a pivot since that is used to turn row values into column aggregations such as sums.

    Use two common table expressions, a full join, and a bunch of calculations and conversions.

    Solution is below creates the following output.

    I assume you have a existing database named [test] to play with the solution in.

    Sincerely

    John

    --

    -- Results

    --

    my_fweekmy_prod_desciw_totaliw_pctoow_totaloow_pctgrand_total

    201404Imaging0011001

    201404Latitude1100001

    201404Personal Desktops0021002

    201404Personal Notebooks571.4285714285714228.57142857142867

    201405Imaging0011001

    201405Personal Notebooks266.6666666666667133.33333333333333

    --

    -- Solution

    --

    -- Use the test database

    use test;

    go

    -- Create the table

    Create table gm_table

    (

    SR_Num INT

    , FWEEK INT

    , prod_DESC VARCHAR(255)

    , WarrantyStatus VARCHAR(255)

    , Orders INT

    );

    go

    -- Add data to the table

    INSERT INTO GM_TABLE (SR_Num, FWEEK, prod_DESC, WarrantyStatus, Orders) VALUES

    (869977621,201404,'Personal Notebooks','IW',1),

    (870120681,201404,'Personal Notebooks','IW',1),

    (870903077,201405,'Personal Notebooks','IW',1),

    (871100687,201405,'Personal Notebooks','IW',1),

    (871117976,201404,'Personal Notebooks','IW',1),

    (871117976,201404,'Personal Notebooks','IW',1),

    (871328699,201404,'Personal Notebooks','IW',1),

    (871494818,201404,'Latitude','IW',1),

    (872106684,201404,'Personal Desktops','OOW',1),

    (872246996,201405,'Imaging','OOW',1),

    (872292272,201404,'Imaging','OOW',1),

    (872303637,201405,'Personal Notebooks','OOW',1),

    (872367703,201404,'Personal Notebooks','OOW',1),

    (872430971,201404,'Personal Notebooks','OOW',1),

    (872500235,201404,'Personal Desktops','OOW',1);

    go

    -- Peek at the data

    Select * from GM_TABLE

    order by FWEEK, prod_DESC, WarrantyStatus

    go

    --

    -- Solve business problem, two cte & full join

    --

    ;

    with cte_iw_data

    as

    (

    select fweek, prod_desc, warrantystatus, sum(orders) as iw_total

    from gm_table where warrantystatus = 'IW'

    group by fweek, prod_desc, warrantystatus

    ),

    cte_oow_data

    as

    (

    select fweek, prod_desc, warrantystatus, sum(orders) as oow_total

    from gm_table where warrantystatus = 'OOW'

    group by fweek, prod_desc, warrantystatus

    )

    select

    -- pick first non-null week

    case

    when i.FWEEK is null then o.FWEEK

    else i.FWEEK

    end as my_fweek,

    -- pick first non-null prod desc

    case

    when i.prod_DESC is null then o.prod_DESC

    else i.prod_DESC

    end as my_prod_desc,

    -- iw total

    isnull(iw_total, 0) as iw_total,

    -- make iw pct

    case

    when isnull(iw_total, 0) + isnull(oow_total, 0) = 0 then convert(float, 0)

    else

    convert(float, isnull(iw_total, 0)) / convert(float, ( isnull(iw_total, 0) + isnull(oow_total, 0) )) * convert(float, 100)

    end as iw_pct,

    -- oow total

    isnull(oow_total, 0) as oow_total,

    -- make oow pct

    case

    when isnull(iw_total, 0) + isnull(oow_total, 0) = 0 then convert(float, 0)

    else

    convert(float, isnull(oow_total, 0)) / convert(float, ( isnull(iw_total, 0) + isnull(oow_total, 0) )) * convert(float, 100)

    end as oow_pct,

    -- grand total

    isnull(iw_total, 0) + isnull(oow_total, 0) as grand_total

    from cte_iw_data i full join cte_oow_data o on i.FWEEK = o.FWEEK and i.prod_DESC = o.prod_DESC

    John Miner
    Crafty DBA
    www.craftydba.com

  • Are you serious j.miner? Take a look at J Livingston code, it's way simpler.

    I just would change the having clause for a where clause (to filter the information before grouping it).

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • So, you do not like my first solution? I totally agree it was the quickest thing that came off the press.

    It is like life, if you spend a couple of minutes more looking at it, a simpler solution can be found.

    How about a filtered roll-up? most of the code is for formatting the results.

    --

    -- Solve business problem with a roll-up

    --

    ; with cte_rollup as (

    select

    fweek,

    prod_desc,

    cast(sum(case when warrantystatus = 'IW' then orders else 0 end) as decimal(9,2)) as iw_total,

    cast(sum(case when warrantystatus = 'OOW' then orders else 0 end) as decimal(9,2)) as oow_total,

    cast(sum(orders) as decimal(9,2)) as grand_total

    from gm_table

    group by rollup (fweek, prod_desc)

    )

    select

    fweek, prod_desc, iw_total,

    cast((iw_total/ grand_total * 100) as decimal(9,2)) as iw_pct,

    oow_total,

    cast((oow_total/ grand_total * 100) as decimal(9,2)) as oow_pct

    from cte_rollup where prod_desc is not null

    John Miner
    Crafty DBA
    www.craftydba.com

  • Is there any reason to use ROLLUP when a simple GROUP BY is enough?

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2

Viewing 11 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic. Login to reply