How to the top N value for each division_id in postgresHow to reset postgres' primary key sequence when it falls out of sync?psql: FATAL: Ident authentication failed for user “postgres”How can I drop all the tables in a PostgreSQL database?Select first row in each GROUP BY group?How to switch databases in psql?How to start PostgreSQL server on Mac OS X?How to exit from PostgreSQL command line utility: psqlpostgres: upgrade a user to be a superuser?How to change PostgreSQL user password?Getting error: Peer authentication failed for user “postgres”, when trying to get pgsql working with rails

How to investigate an unknown 1.5GB file named "sudo" in my Linux home directory?

How can I fix cracks between the bathtub and the wall surround?

Generic method to call API functions with simple retrial on errors

In what language did Túrin converse with Mím?

Coupling two 15 Amp circuit breaker for 20 Amp

What is the purpose of Strength, Intelligence and Dexterity in Path of Exile?

What is the sound/audio equivalent of "unsightly"?

How do I portray irrational anger in first person?

Answer with an image of my favorite musician

Cauterizing a wound with metal?

Create a list of snaking numbers under 50,000

What is this "opened" cube called?

Why is there no Disney logo in MCU movies?

Does Dovescape counter Enchantment Creatures?

Why military weather satellites?

What does なんだって mean in this case? 「そういう子なんだってだけで...」

Should I use the words "pyromancy" and "necromancy" even if they don't mean what people think they do?

In Endgame, wouldn't Stark have remembered Hulk busting out of the stairwell?

Board Chinese train at a different station (on-route)

Why is "I let him to sleep" incorrect (or is it)?

Moscow SVO airport, how to avoid scam taxis without pre-booking?

Don't look at what I did there

Was a six-engine 747 ever seriously considered by Boeing?

Why is 3/4 a simple meter while 6/8 is a compound meter?



How to the top N value for each division_id in postgres


How to reset postgres' primary key sequence when it falls out of sync?psql: FATAL: Ident authentication failed for user “postgres”How can I drop all the tables in a PostgreSQL database?Select first row in each GROUP BY group?How to switch databases in psql?How to start PostgreSQL server on Mac OS X?How to exit from PostgreSQL command line utility: psqlpostgres: upgrade a user to be a superuser?How to change PostgreSQL user password?Getting error: Peer authentication failed for user “postgres”, when trying to get pgsql working with rails






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0















I have a table worker with columns id, name, salary, division_id and I need to display the workers with the top 3 salaries in each division. Here is sample data for table worker:



insert into worker values (1, 'Joe', 70000, 1);
insert into worker values (2, 'Henry', 80000, 2);
insert into worker values (3, 'Sam', 60000, 2);
insert into worker values (4, 'Max', 90000, 1);
insert into worker values (5, 'Janet', 69000, 1);
insert into worker values (6, 'Randy', 85000, 1);
insert into worker values (7, 'Jordan', 70000, 4);
insert into worker values (8, 'Adam', 69000, 3);
insert into worker values (9, 'David', 76000, 4);
insert into worker values (10, 'Moses', 68000, 4);
insert into worker values (11, 'Solomon', 55000, 4);
insert into worker values (12, 'Cloe', 38000, 3);
insert into worker values (13, 'Sarah', 88000, 3);
insert into worker values (14, 'Deb', 92000, 3);
insert into worker values (15, 'Lea', 98000, 4);
commit;


Table WORKER sample data



For the above sample data my query should return the following rows:
Query result for sample data



Note: division 2 has only 2 rows because it has only 2 rows in sample data.



The query should be in Oracle or PostgreSQL.



I know I can limit the number of rows with Oracle's ROWNUM or Postgres LIMIT keyword, but it doesn't help me here as I need to retrieve 3 rows or less for each division_id.



My query should be efficient as possible because the number of rows in workers can be huge (I don't know the exact row count).



In my solution, I am using a CURSOR and FOR my_rec IN my_cursor to scan the result-set and print only the first 3 rows or fewer for every division_id. This solution gives me the complexity of O(N), and I am hoping to find a better solution, maybe solve it with a single query without the use of CURSOR.



DECLARE
CREATE CURSOR my_cursor IS
SELECT division_id, name AS worker, salary
FROM worker
ORDER BY division_id, salary desc;
division_id NUMBER;
row_count_per_id NUMBER;
BEGIN
FOR my_rec IN my_cursor LOOP
-- If first iteration then initialize variables
IF (row_num = 0) THEN
division_id := myRec.division_id;
row_count_per_id := 1;
END IF;

-- row_num can't be 0 at this point
IF (division_id = myRec.division_id) THEN
IF (row_count_per_id < 3) THEN
-- Print first record of the new division_id
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
row_count_per_id := row_count_per_id + 1;
END IF;
ELSE
-- division_id has changed from the previous row
-- Add the first row of new division_id
division_id = myRec.division_id;
row_count_per_id := 1;
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
END IF;
END LOOP;
END;









share|improve this question


























  • Corrected and updated

    – Binyamin Regev
    Mar 30 at 9:59

















0















I have a table worker with columns id, name, salary, division_id and I need to display the workers with the top 3 salaries in each division. Here is sample data for table worker:



insert into worker values (1, 'Joe', 70000, 1);
insert into worker values (2, 'Henry', 80000, 2);
insert into worker values (3, 'Sam', 60000, 2);
insert into worker values (4, 'Max', 90000, 1);
insert into worker values (5, 'Janet', 69000, 1);
insert into worker values (6, 'Randy', 85000, 1);
insert into worker values (7, 'Jordan', 70000, 4);
insert into worker values (8, 'Adam', 69000, 3);
insert into worker values (9, 'David', 76000, 4);
insert into worker values (10, 'Moses', 68000, 4);
insert into worker values (11, 'Solomon', 55000, 4);
insert into worker values (12, 'Cloe', 38000, 3);
insert into worker values (13, 'Sarah', 88000, 3);
insert into worker values (14, 'Deb', 92000, 3);
insert into worker values (15, 'Lea', 98000, 4);
commit;


Table WORKER sample data



For the above sample data my query should return the following rows:
Query result for sample data



Note: division 2 has only 2 rows because it has only 2 rows in sample data.



The query should be in Oracle or PostgreSQL.



I know I can limit the number of rows with Oracle's ROWNUM or Postgres LIMIT keyword, but it doesn't help me here as I need to retrieve 3 rows or less for each division_id.



My query should be efficient as possible because the number of rows in workers can be huge (I don't know the exact row count).



In my solution, I am using a CURSOR and FOR my_rec IN my_cursor to scan the result-set and print only the first 3 rows or fewer for every division_id. This solution gives me the complexity of O(N), and I am hoping to find a better solution, maybe solve it with a single query without the use of CURSOR.



DECLARE
CREATE CURSOR my_cursor IS
SELECT division_id, name AS worker, salary
FROM worker
ORDER BY division_id, salary desc;
division_id NUMBER;
row_count_per_id NUMBER;
BEGIN
FOR my_rec IN my_cursor LOOP
-- If first iteration then initialize variables
IF (row_num = 0) THEN
division_id := myRec.division_id;
row_count_per_id := 1;
END IF;

-- row_num can't be 0 at this point
IF (division_id = myRec.division_id) THEN
IF (row_count_per_id < 3) THEN
-- Print first record of the new division_id
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
row_count_per_id := row_count_per_id + 1;
END IF;
ELSE
-- division_id has changed from the previous row
-- Add the first row of new division_id
division_id = myRec.division_id;
row_count_per_id := 1;
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
END IF;
END LOOP;
END;









share|improve this question


























  • Corrected and updated

    – Binyamin Regev
    Mar 30 at 9:59













0












0








0








I have a table worker with columns id, name, salary, division_id and I need to display the workers with the top 3 salaries in each division. Here is sample data for table worker:



insert into worker values (1, 'Joe', 70000, 1);
insert into worker values (2, 'Henry', 80000, 2);
insert into worker values (3, 'Sam', 60000, 2);
insert into worker values (4, 'Max', 90000, 1);
insert into worker values (5, 'Janet', 69000, 1);
insert into worker values (6, 'Randy', 85000, 1);
insert into worker values (7, 'Jordan', 70000, 4);
insert into worker values (8, 'Adam', 69000, 3);
insert into worker values (9, 'David', 76000, 4);
insert into worker values (10, 'Moses', 68000, 4);
insert into worker values (11, 'Solomon', 55000, 4);
insert into worker values (12, 'Cloe', 38000, 3);
insert into worker values (13, 'Sarah', 88000, 3);
insert into worker values (14, 'Deb', 92000, 3);
insert into worker values (15, 'Lea', 98000, 4);
commit;


Table WORKER sample data



For the above sample data my query should return the following rows:
Query result for sample data



Note: division 2 has only 2 rows because it has only 2 rows in sample data.



The query should be in Oracle or PostgreSQL.



I know I can limit the number of rows with Oracle's ROWNUM or Postgres LIMIT keyword, but it doesn't help me here as I need to retrieve 3 rows or less for each division_id.



My query should be efficient as possible because the number of rows in workers can be huge (I don't know the exact row count).



In my solution, I am using a CURSOR and FOR my_rec IN my_cursor to scan the result-set and print only the first 3 rows or fewer for every division_id. This solution gives me the complexity of O(N), and I am hoping to find a better solution, maybe solve it with a single query without the use of CURSOR.



DECLARE
CREATE CURSOR my_cursor IS
SELECT division_id, name AS worker, salary
FROM worker
ORDER BY division_id, salary desc;
division_id NUMBER;
row_count_per_id NUMBER;
BEGIN
FOR my_rec IN my_cursor LOOP
-- If first iteration then initialize variables
IF (row_num = 0) THEN
division_id := myRec.division_id;
row_count_per_id := 1;
END IF;

-- row_num can't be 0 at this point
IF (division_id = myRec.division_id) THEN
IF (row_count_per_id < 3) THEN
-- Print first record of the new division_id
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
row_count_per_id := row_count_per_id + 1;
END IF;
ELSE
-- division_id has changed from the previous row
-- Add the first row of new division_id
division_id = myRec.division_id;
row_count_per_id := 1;
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
END IF;
END LOOP;
END;









share|improve this question
















I have a table worker with columns id, name, salary, division_id and I need to display the workers with the top 3 salaries in each division. Here is sample data for table worker:



insert into worker values (1, 'Joe', 70000, 1);
insert into worker values (2, 'Henry', 80000, 2);
insert into worker values (3, 'Sam', 60000, 2);
insert into worker values (4, 'Max', 90000, 1);
insert into worker values (5, 'Janet', 69000, 1);
insert into worker values (6, 'Randy', 85000, 1);
insert into worker values (7, 'Jordan', 70000, 4);
insert into worker values (8, 'Adam', 69000, 3);
insert into worker values (9, 'David', 76000, 4);
insert into worker values (10, 'Moses', 68000, 4);
insert into worker values (11, 'Solomon', 55000, 4);
insert into worker values (12, 'Cloe', 38000, 3);
insert into worker values (13, 'Sarah', 88000, 3);
insert into worker values (14, 'Deb', 92000, 3);
insert into worker values (15, 'Lea', 98000, 4);
commit;


Table WORKER sample data



For the above sample data my query should return the following rows:
Query result for sample data



Note: division 2 has only 2 rows because it has only 2 rows in sample data.



The query should be in Oracle or PostgreSQL.



I know I can limit the number of rows with Oracle's ROWNUM or Postgres LIMIT keyword, but it doesn't help me here as I need to retrieve 3 rows or less for each division_id.



My query should be efficient as possible because the number of rows in workers can be huge (I don't know the exact row count).



In my solution, I am using a CURSOR and FOR my_rec IN my_cursor to scan the result-set and print only the first 3 rows or fewer for every division_id. This solution gives me the complexity of O(N), and I am hoping to find a better solution, maybe solve it with a single query without the use of CURSOR.



DECLARE
CREATE CURSOR my_cursor IS
SELECT division_id, name AS worker, salary
FROM worker
ORDER BY division_id, salary desc;
division_id NUMBER;
row_count_per_id NUMBER;
BEGIN
FOR my_rec IN my_cursor LOOP
-- If first iteration then initialize variables
IF (row_num = 0) THEN
division_id := myRec.division_id;
row_count_per_id := 1;
END IF;

-- row_num can't be 0 at this point
IF (division_id = myRec.division_id) THEN
IF (row_count_per_id < 3) THEN
-- Print first record of the new division_id
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
row_count_per_id := row_count_per_id + 1;
END IF;
ELSE
-- division_id has changed from the previous row
-- Add the first row of new division_id
division_id = myRec.division_id;
row_count_per_id := 1;
DBMS_OUTPUT.PUT_LINE('division_id = ' || myRec.division_id ||
', Worker = ' myRec.worker ||
', salary = ' myRec.salary;
END IF;
END LOOP;
END;






oracle postgresql plsql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 30 at 9:59







Binyamin Regev

















asked Mar 27 at 22:16









Binyamin RegevBinyamin Regev

3811 gold badge6 silver badges21 bronze badges




3811 gold badge6 silver badges21 bronze badges















  • Corrected and updated

    – Binyamin Regev
    Mar 30 at 9:59

















  • Corrected and updated

    – Binyamin Regev
    Mar 30 at 9:59
















Corrected and updated

– Binyamin Regev
Mar 30 at 9:59





Corrected and updated

– Binyamin Regev
Mar 30 at 9:59












1 Answer
1






active

oldest

votes


















1















Simply use a query with row_number



WITH c AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY division_id ORDER BY Salary DESC) AS rn
FROM worker
)
SELECT *
FROM c
WHERE rn <= 3


Depending on whether you want salaries that are equal receive the same rank and
be given sequential rank or otherwise, you may use RANK or DENSE_RANK in place of ROW_NUMBER






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%2f55387320%2fhow-to-the-top-n-value-for-each-division-id-in-postgres%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1















    Simply use a query with row_number



    WITH c AS
    (
    SELECT *,
    ROW_NUMBER() OVER (PARTITION BY division_id ORDER BY Salary DESC) AS rn
    FROM worker
    )
    SELECT *
    FROM c
    WHERE rn <= 3


    Depending on whether you want salaries that are equal receive the same rank and
    be given sequential rank or otherwise, you may use RANK or DENSE_RANK in place of ROW_NUMBER






    share|improve this answer





























      1















      Simply use a query with row_number



      WITH c AS
      (
      SELECT *,
      ROW_NUMBER() OVER (PARTITION BY division_id ORDER BY Salary DESC) AS rn
      FROM worker
      )
      SELECT *
      FROM c
      WHERE rn <= 3


      Depending on whether you want salaries that are equal receive the same rank and
      be given sequential rank or otherwise, you may use RANK or DENSE_RANK in place of ROW_NUMBER






      share|improve this answer



























        1














        1










        1









        Simply use a query with row_number



        WITH c AS
        (
        SELECT *,
        ROW_NUMBER() OVER (PARTITION BY division_id ORDER BY Salary DESC) AS rn
        FROM worker
        )
        SELECT *
        FROM c
        WHERE rn <= 3


        Depending on whether you want salaries that are equal receive the same rank and
        be given sequential rank or otherwise, you may use RANK or DENSE_RANK in place of ROW_NUMBER






        share|improve this answer













        Simply use a query with row_number



        WITH c AS
        (
        SELECT *,
        ROW_NUMBER() OVER (PARTITION BY division_id ORDER BY Salary DESC) AS rn
        FROM worker
        )
        SELECT *
        FROM c
        WHERE rn <= 3


        Depending on whether you want salaries that are equal receive the same rank and
        be given sequential rank or otherwise, you may use RANK or DENSE_RANK in place of ROW_NUMBER







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 28 at 4:32









        Kaushik NayakKaushik Nayak

        26k5 gold badges14 silver badges33 bronze badges




        26k5 gold badges14 silver badges33 bronze badges





















            Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.







            Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.



















            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%2f55387320%2fhow-to-the-top-n-value-for-each-division-id-in-postgres%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

            Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

            Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

            Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript