MSSQL get top 4 values from 12 columns












4















I need some assistance here. I have a result set as per below:



Name | IdNumber | Subject1 |Percentage | Subject2 | Percentage | Subject3 | Percentage | (...until subject 12)


I need to return only the 4 subjects and their percentage that the student scored the highest in.



Getting the highest mark per student is easy, I've done it this way:



SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]


Getting the other 4 is the problem.










share|improve this question




















  • 2





    Add some sample table data and the expected result - all as formatted text, not images. Consider simplifying the problem, perhaps just 3 subjects will do fine?

    – jarlh
    Nov 16 '18 at 9:14






  • 2





    Why not fix your table structure first? Having repeated groups of columns is a broken design.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:30






  • 3





    Normalising the schema design would make this sort of query a lot easier. If the person who demands a flat table design is stuck in their ways, perhaps create a view to satisfy them while keeping a sensible design under the hood?

    – Diado
    Nov 16 '18 at 9:38








  • 3





    How they want to have the data presented to them should not dictate how the data is stored.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:38






  • 1





    If you created that table, change it: Create the table normalized and add a view PIVOting it for the person who requested that result

    – dnoeth
    Nov 16 '18 at 9:50
















4















I need some assistance here. I have a result set as per below:



Name | IdNumber | Subject1 |Percentage | Subject2 | Percentage | Subject3 | Percentage | (...until subject 12)


I need to return only the 4 subjects and their percentage that the student scored the highest in.



Getting the highest mark per student is easy, I've done it this way:



SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]


Getting the other 4 is the problem.










share|improve this question




















  • 2





    Add some sample table data and the expected result - all as formatted text, not images. Consider simplifying the problem, perhaps just 3 subjects will do fine?

    – jarlh
    Nov 16 '18 at 9:14






  • 2





    Why not fix your table structure first? Having repeated groups of columns is a broken design.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:30






  • 3





    Normalising the schema design would make this sort of query a lot easier. If the person who demands a flat table design is stuck in their ways, perhaps create a view to satisfy them while keeping a sensible design under the hood?

    – Diado
    Nov 16 '18 at 9:38








  • 3





    How they want to have the data presented to them should not dictate how the data is stored.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:38






  • 1





    If you created that table, change it: Create the table normalized and add a view PIVOting it for the person who requested that result

    – dnoeth
    Nov 16 '18 at 9:50














4












4








4








I need some assistance here. I have a result set as per below:



Name | IdNumber | Subject1 |Percentage | Subject2 | Percentage | Subject3 | Percentage | (...until subject 12)


I need to return only the 4 subjects and their percentage that the student scored the highest in.



Getting the highest mark per student is easy, I've done it this way:



SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]


Getting the other 4 is the problem.










share|improve this question
















I need some assistance here. I have a result set as per below:



Name | IdNumber | Subject1 |Percentage | Subject2 | Percentage | Subject3 | Percentage | (...until subject 12)


I need to return only the 4 subjects and their percentage that the student scored the highest in.



Getting the highest mark per student is easy, I've done it this way:



SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]


Getting the other 4 is the problem.







sql sql-server tsql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 15:20









Andy Hames

32419




32419










asked Nov 16 '18 at 9:12









KalynKalyn

404




404








  • 2





    Add some sample table data and the expected result - all as formatted text, not images. Consider simplifying the problem, perhaps just 3 subjects will do fine?

    – jarlh
    Nov 16 '18 at 9:14






  • 2





    Why not fix your table structure first? Having repeated groups of columns is a broken design.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:30






  • 3





    Normalising the schema design would make this sort of query a lot easier. If the person who demands a flat table design is stuck in their ways, perhaps create a view to satisfy them while keeping a sensible design under the hood?

    – Diado
    Nov 16 '18 at 9:38








  • 3





    How they want to have the data presented to them should not dictate how the data is stored.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:38






  • 1





    If you created that table, change it: Create the table normalized and add a view PIVOting it for the person who requested that result

    – dnoeth
    Nov 16 '18 at 9:50














  • 2





    Add some sample table data and the expected result - all as formatted text, not images. Consider simplifying the problem, perhaps just 3 subjects will do fine?

    – jarlh
    Nov 16 '18 at 9:14






  • 2





    Why not fix your table structure first? Having repeated groups of columns is a broken design.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:30






  • 3





    Normalising the schema design would make this sort of query a lot easier. If the person who demands a flat table design is stuck in their ways, perhaps create a view to satisfy them while keeping a sensible design under the hood?

    – Diado
    Nov 16 '18 at 9:38








  • 3





    How they want to have the data presented to them should not dictate how the data is stored.

    – Damien_The_Unbeliever
    Nov 16 '18 at 9:38






  • 1





    If you created that table, change it: Create the table normalized and add a view PIVOting it for the person who requested that result

    – dnoeth
    Nov 16 '18 at 9:50








2




2





Add some sample table data and the expected result - all as formatted text, not images. Consider simplifying the problem, perhaps just 3 subjects will do fine?

– jarlh
Nov 16 '18 at 9:14





Add some sample table data and the expected result - all as formatted text, not images. Consider simplifying the problem, perhaps just 3 subjects will do fine?

– jarlh
Nov 16 '18 at 9:14




2




2





Why not fix your table structure first? Having repeated groups of columns is a broken design.

– Damien_The_Unbeliever
Nov 16 '18 at 9:30





Why not fix your table structure first? Having repeated groups of columns is a broken design.

– Damien_The_Unbeliever
Nov 16 '18 at 9:30




3




3





Normalising the schema design would make this sort of query a lot easier. If the person who demands a flat table design is stuck in their ways, perhaps create a view to satisfy them while keeping a sensible design under the hood?

– Diado
Nov 16 '18 at 9:38







Normalising the schema design would make this sort of query a lot easier. If the person who demands a flat table design is stuck in their ways, perhaps create a view to satisfy them while keeping a sensible design under the hood?

– Diado
Nov 16 '18 at 9:38






3




3





How they want to have the data presented to them should not dictate how the data is stored.

– Damien_The_Unbeliever
Nov 16 '18 at 9:38





How they want to have the data presented to them should not dictate how the data is stored.

– Damien_The_Unbeliever
Nov 16 '18 at 9:38




1




1





If you created that table, change it: Create the table normalized and add a view PIVOting it for the person who requested that result

– dnoeth
Nov 16 '18 at 9:50





If you created that table, change it: Create the table normalized and add a view PIVOting it for the person who requested that result

– dnoeth
Nov 16 '18 at 9:50












4 Answers
4






active

oldest

votes


















1














Try to unpivot data as the data you have is not normalised and then pivot data again.



Preparing data:



DECLARE @FooTable TABLE 
( Name VARCHAR(10), IdNumber INT,
Subject1 VARCHAR(100), Percentage1 INT,
Subject2 VARCHAR(10), Percentage2 INT,
Subject3 VARCHAR(10), Percentage3 INT,
Subject4 VARCHAR(10), Percentage4 INT
)

INSERT INTO @FooTable
(
Name, IdNumber,
Subject1, Percentage1,
Subject2, Percentage2,
Subject3, Percentage3,
Subject4, Percentage4
)


VALUES
( 'Name 1', -- Name - varchar(10)
1,
'Subject 1', -- Subject1 - varchar(10)
10, -- Percentage1 - int
'Subject 2', -- Subject2 - varchar(10)
20, -- Percentage2 - int
'Subject 3', -- Subject3 - varchar(10)
30, -- Percentage3 - int
'Subject 4', -- Subject4 - varchar(10)
40 -- Percentage4 - int
)
, ('Name 2', -- Name - varchar(10)
2,
'Subject 1', -- Subject1 - varchar(10)
20, -- Percentage1 - int
'Subject 2', -- Subject2 - varchar(10)
30, -- Percentage2 - int
'Subject 3', -- Subject3 - varchar(10)
40, -- Percentage3 - int
'Subject 4', -- Subject4 - varchar(10)
50 -- Percentage4 - int)
)
, ('Name 3', -- Name - varchar(10)
3,
'Subject 1', -- Subject1 - varchar(10)
30, -- Percentage1 - int
'Subject 2', -- Subject2 - varchar(10)
40, -- Percentage2 - int
'Subject 3', -- Subject3 - varchar(10)
50, -- Percentage3 - int
'Subject 4', -- Subject4 - varchar(10)
60 -- Percentage4 - int)
)

SELECT * FROM @FooTable


Unpivoting data and pivoting data:



;WITH cte
AS (SELECT *,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY percentage DESC) AS rn
FROM
(
SELECT Name,
Percentage1,
Percentage2,
Percentage3,
Percentage4
FROM @FooTable
) p
UNPIVOT
(
percentage
FOR subject IN (Percentage1, Percentage2, Percentage3, Percentage4)
) up)
SELECT *
FROM (
SELECT cte.percentage, cte.subject
FROM cte
WHERE rn IN ( 1, 2, 3, 4 )
)source
PIVOT
(
MAX(percentage)
FOR subject IN ([Percentage1],[Percentage2],[Percentage3],[Percentage4])
)q


Output:



enter image description here






share|improve this answer
























  • Here while pivoting the data in the result set we need to consider all the 12 combinations because the top 4 subjects will be different for each student

    – Sanal Sunny
    Nov 16 '18 at 13:04











  • @SanalSunny OP can add these columns into the table.

    – StepUp
    Nov 16 '18 at 13:14



















3














If you don't wish to change your table structure then you need to UNPIVOT the data after that you can select the top 4 subjects



;WITH cte AS (
SELECT *,ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Percentage DESC) AS rn
FROM
(SELECT Name,percentage1,percentage2,percentage3,percentage4
,percentage5,percentage6,percentage7,percentage8
,percentage9,percentage10,percentage11,percentage12
FROM r ) p
UNPIVOT
(percentage FOR subject IN (,percentage1,percentage2,percentage3,percentage4
,percentage5,percentage6,percentage7,percentage8
,percentage9,percentage10,percentage11,percentage12)
) up )
SELECT * FROM cte
WHERE rn IN (1,2,3,4)





share|improve this answer
























  • Thank you for making me aware of the PIVOT and UNPIVOT operators. :-)

    – johey
    Nov 16 '18 at 9:58



















1














The data structure is build in a way that makes things much more complicated as they could be.
You are not allowed to change that. Ok.
We need to do something ugly to deal with that ugly data structure.



Define a view that normalizes the structure. Then you can work in a normal way querying that view.



The view would look like:



select Name, IdNumber, Subject1 as Subject, Percentage1 as Percentage, 1 as SubjectNumber
union all
select Name, IdNumber, Subject2 as Subject, Percentage2 as Percentage, 2 as SubjectNumber
...


That should be much easier to deal with.



If this was for production somehow, you should try to set things straight much earlier.






share|improve this answer





















  • 1





    Better switch to UNION ALL

    – dnoeth
    Nov 16 '18 at 9:51











  • @dnoeth You're right

    – jhinghaus
    Nov 16 '18 at 9:53











  • Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post

    – Kalyn
    Nov 16 '18 at 12:09



















1














Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53334654%2fmssql-get-top-4-values-from-12-columns%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Try to unpivot data as the data you have is not normalised and then pivot data again.



    Preparing data:



    DECLARE @FooTable TABLE 
    ( Name VARCHAR(10), IdNumber INT,
    Subject1 VARCHAR(100), Percentage1 INT,
    Subject2 VARCHAR(10), Percentage2 INT,
    Subject3 VARCHAR(10), Percentage3 INT,
    Subject4 VARCHAR(10), Percentage4 INT
    )

    INSERT INTO @FooTable
    (
    Name, IdNumber,
    Subject1, Percentage1,
    Subject2, Percentage2,
    Subject3, Percentage3,
    Subject4, Percentage4
    )


    VALUES
    ( 'Name 1', -- Name - varchar(10)
    1,
    'Subject 1', -- Subject1 - varchar(10)
    10, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    20, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    30, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    40 -- Percentage4 - int
    )
    , ('Name 2', -- Name - varchar(10)
    2,
    'Subject 1', -- Subject1 - varchar(10)
    20, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    30, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    40, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    50 -- Percentage4 - int)
    )
    , ('Name 3', -- Name - varchar(10)
    3,
    'Subject 1', -- Subject1 - varchar(10)
    30, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    40, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    50, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    60 -- Percentage4 - int)
    )

    SELECT * FROM @FooTable


    Unpivoting data and pivoting data:



    ;WITH cte
    AS (SELECT *,
    ROW_NUMBER() OVER (PARTITION BY Name ORDER BY percentage DESC) AS rn
    FROM
    (
    SELECT Name,
    Percentage1,
    Percentage2,
    Percentage3,
    Percentage4
    FROM @FooTable
    ) p
    UNPIVOT
    (
    percentage
    FOR subject IN (Percentage1, Percentage2, Percentage3, Percentage4)
    ) up)
    SELECT *
    FROM (
    SELECT cte.percentage, cte.subject
    FROM cte
    WHERE rn IN ( 1, 2, 3, 4 )
    )source
    PIVOT
    (
    MAX(percentage)
    FOR subject IN ([Percentage1],[Percentage2],[Percentage3],[Percentage4])
    )q


    Output:



    enter image description here






    share|improve this answer
























    • Here while pivoting the data in the result set we need to consider all the 12 combinations because the top 4 subjects will be different for each student

      – Sanal Sunny
      Nov 16 '18 at 13:04











    • @SanalSunny OP can add these columns into the table.

      – StepUp
      Nov 16 '18 at 13:14
















    1














    Try to unpivot data as the data you have is not normalised and then pivot data again.



    Preparing data:



    DECLARE @FooTable TABLE 
    ( Name VARCHAR(10), IdNumber INT,
    Subject1 VARCHAR(100), Percentage1 INT,
    Subject2 VARCHAR(10), Percentage2 INT,
    Subject3 VARCHAR(10), Percentage3 INT,
    Subject4 VARCHAR(10), Percentage4 INT
    )

    INSERT INTO @FooTable
    (
    Name, IdNumber,
    Subject1, Percentage1,
    Subject2, Percentage2,
    Subject3, Percentage3,
    Subject4, Percentage4
    )


    VALUES
    ( 'Name 1', -- Name - varchar(10)
    1,
    'Subject 1', -- Subject1 - varchar(10)
    10, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    20, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    30, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    40 -- Percentage4 - int
    )
    , ('Name 2', -- Name - varchar(10)
    2,
    'Subject 1', -- Subject1 - varchar(10)
    20, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    30, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    40, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    50 -- Percentage4 - int)
    )
    , ('Name 3', -- Name - varchar(10)
    3,
    'Subject 1', -- Subject1 - varchar(10)
    30, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    40, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    50, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    60 -- Percentage4 - int)
    )

    SELECT * FROM @FooTable


    Unpivoting data and pivoting data:



    ;WITH cte
    AS (SELECT *,
    ROW_NUMBER() OVER (PARTITION BY Name ORDER BY percentage DESC) AS rn
    FROM
    (
    SELECT Name,
    Percentage1,
    Percentage2,
    Percentage3,
    Percentage4
    FROM @FooTable
    ) p
    UNPIVOT
    (
    percentage
    FOR subject IN (Percentage1, Percentage2, Percentage3, Percentage4)
    ) up)
    SELECT *
    FROM (
    SELECT cte.percentage, cte.subject
    FROM cte
    WHERE rn IN ( 1, 2, 3, 4 )
    )source
    PIVOT
    (
    MAX(percentage)
    FOR subject IN ([Percentage1],[Percentage2],[Percentage3],[Percentage4])
    )q


    Output:



    enter image description here






    share|improve this answer
























    • Here while pivoting the data in the result set we need to consider all the 12 combinations because the top 4 subjects will be different for each student

      – Sanal Sunny
      Nov 16 '18 at 13:04











    • @SanalSunny OP can add these columns into the table.

      – StepUp
      Nov 16 '18 at 13:14














    1












    1








    1







    Try to unpivot data as the data you have is not normalised and then pivot data again.



    Preparing data:



    DECLARE @FooTable TABLE 
    ( Name VARCHAR(10), IdNumber INT,
    Subject1 VARCHAR(100), Percentage1 INT,
    Subject2 VARCHAR(10), Percentage2 INT,
    Subject3 VARCHAR(10), Percentage3 INT,
    Subject4 VARCHAR(10), Percentage4 INT
    )

    INSERT INTO @FooTable
    (
    Name, IdNumber,
    Subject1, Percentage1,
    Subject2, Percentage2,
    Subject3, Percentage3,
    Subject4, Percentage4
    )


    VALUES
    ( 'Name 1', -- Name - varchar(10)
    1,
    'Subject 1', -- Subject1 - varchar(10)
    10, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    20, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    30, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    40 -- Percentage4 - int
    )
    , ('Name 2', -- Name - varchar(10)
    2,
    'Subject 1', -- Subject1 - varchar(10)
    20, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    30, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    40, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    50 -- Percentage4 - int)
    )
    , ('Name 3', -- Name - varchar(10)
    3,
    'Subject 1', -- Subject1 - varchar(10)
    30, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    40, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    50, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    60 -- Percentage4 - int)
    )

    SELECT * FROM @FooTable


    Unpivoting data and pivoting data:



    ;WITH cte
    AS (SELECT *,
    ROW_NUMBER() OVER (PARTITION BY Name ORDER BY percentage DESC) AS rn
    FROM
    (
    SELECT Name,
    Percentage1,
    Percentage2,
    Percentage3,
    Percentage4
    FROM @FooTable
    ) p
    UNPIVOT
    (
    percentage
    FOR subject IN (Percentage1, Percentage2, Percentage3, Percentage4)
    ) up)
    SELECT *
    FROM (
    SELECT cte.percentage, cte.subject
    FROM cte
    WHERE rn IN ( 1, 2, 3, 4 )
    )source
    PIVOT
    (
    MAX(percentage)
    FOR subject IN ([Percentage1],[Percentage2],[Percentage3],[Percentage4])
    )q


    Output:



    enter image description here






    share|improve this answer













    Try to unpivot data as the data you have is not normalised and then pivot data again.



    Preparing data:



    DECLARE @FooTable TABLE 
    ( Name VARCHAR(10), IdNumber INT,
    Subject1 VARCHAR(100), Percentage1 INT,
    Subject2 VARCHAR(10), Percentage2 INT,
    Subject3 VARCHAR(10), Percentage3 INT,
    Subject4 VARCHAR(10), Percentage4 INT
    )

    INSERT INTO @FooTable
    (
    Name, IdNumber,
    Subject1, Percentage1,
    Subject2, Percentage2,
    Subject3, Percentage3,
    Subject4, Percentage4
    )


    VALUES
    ( 'Name 1', -- Name - varchar(10)
    1,
    'Subject 1', -- Subject1 - varchar(10)
    10, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    20, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    30, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    40 -- Percentage4 - int
    )
    , ('Name 2', -- Name - varchar(10)
    2,
    'Subject 1', -- Subject1 - varchar(10)
    20, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    30, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    40, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    50 -- Percentage4 - int)
    )
    , ('Name 3', -- Name - varchar(10)
    3,
    'Subject 1', -- Subject1 - varchar(10)
    30, -- Percentage1 - int
    'Subject 2', -- Subject2 - varchar(10)
    40, -- Percentage2 - int
    'Subject 3', -- Subject3 - varchar(10)
    50, -- Percentage3 - int
    'Subject 4', -- Subject4 - varchar(10)
    60 -- Percentage4 - int)
    )

    SELECT * FROM @FooTable


    Unpivoting data and pivoting data:



    ;WITH cte
    AS (SELECT *,
    ROW_NUMBER() OVER (PARTITION BY Name ORDER BY percentage DESC) AS rn
    FROM
    (
    SELECT Name,
    Percentage1,
    Percentage2,
    Percentage3,
    Percentage4
    FROM @FooTable
    ) p
    UNPIVOT
    (
    percentage
    FOR subject IN (Percentage1, Percentage2, Percentage3, Percentage4)
    ) up)
    SELECT *
    FROM (
    SELECT cte.percentage, cte.subject
    FROM cte
    WHERE rn IN ( 1, 2, 3, 4 )
    )source
    PIVOT
    (
    MAX(percentage)
    FOR subject IN ([Percentage1],[Percentage2],[Percentage3],[Percentage4])
    )q


    Output:



    enter image description here







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 16 '18 at 10:19









    StepUpStepUp

    7,40474473




    7,40474473













    • Here while pivoting the data in the result set we need to consider all the 12 combinations because the top 4 subjects will be different for each student

      – Sanal Sunny
      Nov 16 '18 at 13:04











    • @SanalSunny OP can add these columns into the table.

      – StepUp
      Nov 16 '18 at 13:14



















    • Here while pivoting the data in the result set we need to consider all the 12 combinations because the top 4 subjects will be different for each student

      – Sanal Sunny
      Nov 16 '18 at 13:04











    • @SanalSunny OP can add these columns into the table.

      – StepUp
      Nov 16 '18 at 13:14

















    Here while pivoting the data in the result set we need to consider all the 12 combinations because the top 4 subjects will be different for each student

    – Sanal Sunny
    Nov 16 '18 at 13:04





    Here while pivoting the data in the result set we need to consider all the 12 combinations because the top 4 subjects will be different for each student

    – Sanal Sunny
    Nov 16 '18 at 13:04













    @SanalSunny OP can add these columns into the table.

    – StepUp
    Nov 16 '18 at 13:14





    @SanalSunny OP can add these columns into the table.

    – StepUp
    Nov 16 '18 at 13:14













    3














    If you don't wish to change your table structure then you need to UNPIVOT the data after that you can select the top 4 subjects



    ;WITH cte AS (
    SELECT *,ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Percentage DESC) AS rn
    FROM
    (SELECT Name,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12
    FROM r ) p
    UNPIVOT
    (percentage FOR subject IN (,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12)
    ) up )
    SELECT * FROM cte
    WHERE rn IN (1,2,3,4)





    share|improve this answer
























    • Thank you for making me aware of the PIVOT and UNPIVOT operators. :-)

      – johey
      Nov 16 '18 at 9:58
















    3














    If you don't wish to change your table structure then you need to UNPIVOT the data after that you can select the top 4 subjects



    ;WITH cte AS (
    SELECT *,ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Percentage DESC) AS rn
    FROM
    (SELECT Name,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12
    FROM r ) p
    UNPIVOT
    (percentage FOR subject IN (,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12)
    ) up )
    SELECT * FROM cte
    WHERE rn IN (1,2,3,4)





    share|improve this answer
























    • Thank you for making me aware of the PIVOT and UNPIVOT operators. :-)

      – johey
      Nov 16 '18 at 9:58














    3












    3








    3







    If you don't wish to change your table structure then you need to UNPIVOT the data after that you can select the top 4 subjects



    ;WITH cte AS (
    SELECT *,ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Percentage DESC) AS rn
    FROM
    (SELECT Name,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12
    FROM r ) p
    UNPIVOT
    (percentage FOR subject IN (,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12)
    ) up )
    SELECT * FROM cte
    WHERE rn IN (1,2,3,4)





    share|improve this answer













    If you don't wish to change your table structure then you need to UNPIVOT the data after that you can select the top 4 subjects



    ;WITH cte AS (
    SELECT *,ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Percentage DESC) AS rn
    FROM
    (SELECT Name,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12
    FROM r ) p
    UNPIVOT
    (percentage FOR subject IN (,percentage1,percentage2,percentage3,percentage4
    ,percentage5,percentage6,percentage7,percentage8
    ,percentage9,percentage10,percentage11,percentage12)
    ) up )
    SELECT * FROM cte
    WHERE rn IN (1,2,3,4)






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 16 '18 at 9:51









    Sanal SunnySanal Sunny

    6628




    6628













    • Thank you for making me aware of the PIVOT and UNPIVOT operators. :-)

      – johey
      Nov 16 '18 at 9:58



















    • Thank you for making me aware of the PIVOT and UNPIVOT operators. :-)

      – johey
      Nov 16 '18 at 9:58

















    Thank you for making me aware of the PIVOT and UNPIVOT operators. :-)

    – johey
    Nov 16 '18 at 9:58





    Thank you for making me aware of the PIVOT and UNPIVOT operators. :-)

    – johey
    Nov 16 '18 at 9:58











    1














    The data structure is build in a way that makes things much more complicated as they could be.
    You are not allowed to change that. Ok.
    We need to do something ugly to deal with that ugly data structure.



    Define a view that normalizes the structure. Then you can work in a normal way querying that view.



    The view would look like:



    select Name, IdNumber, Subject1 as Subject, Percentage1 as Percentage, 1 as SubjectNumber
    union all
    select Name, IdNumber, Subject2 as Subject, Percentage2 as Percentage, 2 as SubjectNumber
    ...


    That should be much easier to deal with.



    If this was for production somehow, you should try to set things straight much earlier.






    share|improve this answer





















    • 1





      Better switch to UNION ALL

      – dnoeth
      Nov 16 '18 at 9:51











    • @dnoeth You're right

      – jhinghaus
      Nov 16 '18 at 9:53











    • Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post

      – Kalyn
      Nov 16 '18 at 12:09
















    1














    The data structure is build in a way that makes things much more complicated as they could be.
    You are not allowed to change that. Ok.
    We need to do something ugly to deal with that ugly data structure.



    Define a view that normalizes the structure. Then you can work in a normal way querying that view.



    The view would look like:



    select Name, IdNumber, Subject1 as Subject, Percentage1 as Percentage, 1 as SubjectNumber
    union all
    select Name, IdNumber, Subject2 as Subject, Percentage2 as Percentage, 2 as SubjectNumber
    ...


    That should be much easier to deal with.



    If this was for production somehow, you should try to set things straight much earlier.






    share|improve this answer





















    • 1





      Better switch to UNION ALL

      – dnoeth
      Nov 16 '18 at 9:51











    • @dnoeth You're right

      – jhinghaus
      Nov 16 '18 at 9:53











    • Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post

      – Kalyn
      Nov 16 '18 at 12:09














    1












    1








    1







    The data structure is build in a way that makes things much more complicated as they could be.
    You are not allowed to change that. Ok.
    We need to do something ugly to deal with that ugly data structure.



    Define a view that normalizes the structure. Then you can work in a normal way querying that view.



    The view would look like:



    select Name, IdNumber, Subject1 as Subject, Percentage1 as Percentage, 1 as SubjectNumber
    union all
    select Name, IdNumber, Subject2 as Subject, Percentage2 as Percentage, 2 as SubjectNumber
    ...


    That should be much easier to deal with.



    If this was for production somehow, you should try to set things straight much earlier.






    share|improve this answer















    The data structure is build in a way that makes things much more complicated as they could be.
    You are not allowed to change that. Ok.
    We need to do something ugly to deal with that ugly data structure.



    Define a view that normalizes the structure. Then you can work in a normal way querying that view.



    The view would look like:



    select Name, IdNumber, Subject1 as Subject, Percentage1 as Percentage, 1 as SubjectNumber
    union all
    select Name, IdNumber, Subject2 as Subject, Percentage2 as Percentage, 2 as SubjectNumber
    ...


    That should be much easier to deal with.



    If this was for production somehow, you should try to set things straight much earlier.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 16 '18 at 9:54

























    answered Nov 16 '18 at 9:42









    jhinghausjhinghaus

    261517




    261517








    • 1





      Better switch to UNION ALL

      – dnoeth
      Nov 16 '18 at 9:51











    • @dnoeth You're right

      – jhinghaus
      Nov 16 '18 at 9:53











    • Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post

      – Kalyn
      Nov 16 '18 at 12:09














    • 1





      Better switch to UNION ALL

      – dnoeth
      Nov 16 '18 at 9:51











    • @dnoeth You're right

      – jhinghaus
      Nov 16 '18 at 9:53











    • Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post

      – Kalyn
      Nov 16 '18 at 12:09








    1




    1





    Better switch to UNION ALL

    – dnoeth
    Nov 16 '18 at 9:51





    Better switch to UNION ALL

    – dnoeth
    Nov 16 '18 at 9:51













    @dnoeth You're right

    – jhinghaus
    Nov 16 '18 at 9:53





    @dnoeth You're right

    – jhinghaus
    Nov 16 '18 at 9:53













    Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post

    – Kalyn
    Nov 16 '18 at 12:09





    Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post

    – Kalyn
    Nov 16 '18 at 12:09











    1














    Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post






    share|improve this answer




























      1














      Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post






      share|improve this answer


























        1












        1








        1







        Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post






        share|improve this answer













        Thank you Guys for all the assistance. one of the posts helped. but i cant find it now, i think they removed their post







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 16 '18 at 12:09









        KalynKalyn

        404




        404






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53334654%2fmssql-get-top-4-values-from-12-columns%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to pass form data using jquery Ajax to insert data in database?

            National Museum of Racing and Hall of Fame

            Guess what letter conforming each word