如何按性别选择first_name,最高工资组?

问题描述 投票:0回答:4

我有两个表tab1和tab2。

create table tab1 ( emp_id number(2), salary number(4));

insert into tab1 values(1,2000); 
insert into tab1 values(2,3000); 
insert into tab1 values(3,3645); 
insert into tab1 values(4,2143); 
insert into tab1 values(5,2541);

create table tab2( emp_id number(2), first_name varchar2(20), gender varchar2(10) );

insert into tab2 values(1,'aaaa','male'); 
insert into tab2 values(2,'bbbb','female'); 
insert into tab2 values(3,'cccc','male'); 
insert into tab2 values(4,'dddd','female'); 
insert into tab2 values(5,'eeee','male');

我只能通过此查询获得性别和最高工资列,但我还希望看到emp_id和first_name列。这是我的查询......

select m.gender,max(h.salary) 
  from tab2 m 
  join tab1 h 
    on m.emp_id=h.emp_id 
 group by m.gender;
sql oracle greatest-n-per-group
4个回答
2
投票

与其他一些答案一样,两次读取tab2表是低效且无必要的。你可以使用通常被称为MAX..KEEP的东西,但是有什么令人困惑的记录为FIRST函数(here)。

此查询使用该功能为您提供所需的结果:

SELECT  t2.gender,
        max(t2.emp_id) keep ( dense_rank first order by t1.salary desc ) emp_id,
        max(t2.first_name) keep ( dense_rank first order by t1.salary desc ) first_name,
        max(t1.salary)
FROM    tab1 t1
INNER JOIN tab2 t2 ON t2.emp_id = t1.emp_id
GROUP BY t2.gender;

请注意,它只读取每个表一次。

结果:

+--------+--------+------------+----------------+
| GENDER | EMP_ID + FIRST_NAME | MAX(T1.SALARY) |
+--------+--------+------------+----------------+
| female |      2 + bbbb       |           3000 |
| male   |      3 + cccc       |           3645 |
+--------+--------+------------+----------------+

我将断言这是获得所寻求结果的最有效方法。

[我不喜欢在没有蠕动的情况下做出这样的陈述(或者如果你愿意的话,还有“狡猾的话”),因为那里有很多我们都需要学习的东西。但是,如果有更快的方法来进行此查询,那么学习它将值得在SO上进行公开修正。 :)]

UPDATE

顺便说一句,如果你有一个GENDERS表,像这样......

create table genders ( gender varchar2(10) );

insert into genders values ('male');
insert into genders values ('female');

那么这也是12c及以后的合理解决方案:

select g.gender, 
       ca.emp_id, 
       ca.first_name, 
       ca.salary 
from genders g  
CROSS APPLY ( SELECT t2.emp_id, 
                     t2.first_name, 
                     t2.gender, 
                     t1.salary
              FROM   tab1 t1 
              INNER JOIN tab2 t2 on t2.emp_id = t1.emp_id
              WHERE  t2.gender = g.gender
              ORDER BY t1.salary DESC
              FETCH FIRST 1 ROW ONLY ) ca

这种替代方法的好处是:

  1. 更少重复的MAX..KEEP语法,如果你不仅需要emp_idfirst_name而且还需要其他一些列,那么这会很麻烦
  2. 它可以从帮助查询CROSS APPLY的索引中受益。在你的情况下,GENDER的索引不太可能有足够的选择性来帮助,但在其他情况下要记住这一点。

2
投票

您是否需要加入saubquery以获得最大的性别和性别

select  t1.emp_id, , t2.first_name, t.max_sal, t.gender 
from  tab1 t1 
inner join  tab2 t2 on t1.emp_id = t2.emp_id 
inner join  (
  select m.gender,max(h.salary) max_sal
  from tab2 m 
  join tab1 h on m.emp_id=h.emp_id 
  group by m.gender

) t on t.max_sal = t1.salary  and t.gender = t2.gender 

0
投票

选项tab2.gender,tab1.salary,tab1.emp_id,tab2.first_name来自tab1加入tab2 on tab1.emp_id = tab2.emp_id where tab1.salary =(从tab1中选择max(tab1.salary))

enter image description here


-2
投票

你能指出你想要的预期结果吗,我不清楚。 你想得到这样的东西吗? EMP_ID,FIRST_NAME,工资,性别

查询以按薪水排序所有列

select h.emp_id, m.first_name, m.gender,h.salary from tab2 m join tab1 h on m.emp_id=h.emp_id order by h.salary desc;
© www.soinside.com 2019 - 2024. All rights reserved.