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;
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;
For the above sample data my query should return the following rows:
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
add a comment |
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;
For the above sample data my query should return the following rows:
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
Corrected and updated
– Binyamin Regev
Mar 30 at 9:59
add a comment |
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;
For the above sample data my query should return the following rows:
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
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;
For the above sample data my query should return the following rows:
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
oracle postgresql plsql
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
add a comment |
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
add a comment |
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
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
answered Mar 28 at 4:32
Kaushik NayakKaushik Nayak
26k5 gold badges14 silver badges33 bronze badges
26k5 gold badges14 silver badges33 bronze badges
add a comment |
add a comment |
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.
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
Corrected and updated
– Binyamin Regev
Mar 30 at 9:59