【问题标题】:Insert column with Max in sql在sql中插入带Max的列
【发布时间】:2015-11-27 20:14:38
【问题描述】:

我不知道如何插入具有最大值的列。

Select id,MAX(salary),Min(Salary)
from C 
GROUP BY id;

它是给我最大的所有 id 我只想要最高和最低工资的ID!

【问题讨论】:

  • 如果两个id共享最大值怎么办?两个都想要吗?
  • @MichaelBroughton 是的,我愿意。我想同时使用最大值和最小值。

标签: sql oracle greatest-n-per-group


【解决方案1】:

为您提供的几个选项只需要对表进行一次扫描:

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE C ( ID, SALARY ) AS
          SELECT 1, 100 FROM DUAL
UNION ALL SELECT 2, 110 FROM DUAL
UNION ALL SELECT 3, 100 FROM DUAL
UNION ALL SELECT 4, 110 FROM DUAL
UNION ALL SELECT 5,  90 FROM DUAL

查询 1 - 获取单个 ID

SELECT *
FROM (
   SELECT ID, SALARY
   FROM   c
   ORDER BY SALARY DESC
)
WHERE ROWNUM = 1

Results

| ID | SALARY |
|----|--------|
|  2 |    110 |

查询 2 - 获取单个 ID(获取最小和最大 ID 的替代方法)

SELECT MAX( ID ) KEEP ( DENSE_RANK LAST ORDER BY SALARY ) AS MAX_SALARY_ID,
       MAX( SALARY ) AS MAX_SALARY,
       MIN( ID ) KEEP ( DENSE_RANK FIRST ORDER BY SALARY ) AS MIN_SALARY_ID,
       MIN( SALARY ) AS MIN_SALARY
FROM   C

Results

| MAX_SALARY_ID | MAX_SALARY | MIN_SALARY_ID | MIN_SALARY |
|---------------|------------|---------------|------------|
|             4 |        110 |             5 |         90 |

查询 3 - 获取所有最高薪水的 ID

SELECT ID, SALARY
FROM   (
  SELECT ID,
         SALARY,
         RANK() OVER ( ORDER BY SALARY DESC ) AS RNK
  FROM   C
)
WHERE  RNK = 1

Results

| ID | SALARY |
|----|--------|
|  2 |    110 |
|  4 |    110 |

查询 4 ​​- 获取最低和最高工资的所有 ID

SELECT LISTAGG( CASE MIN_RANK WHEN 1 THEN ID END, ',' ) WITHIN GROUP ( ORDER BY ID ) AS MIN_SALARY_IDS,
       MAX( CASE MIN_RANK WHEN 1 THEN SALARY END ) AS MIN_SALARY,
       LISTAGG( CASE MAX_RANK WHEN 1 THEN ID END, ',' ) WITHIN GROUP ( ORDER BY ID ) AS MAX_SALARY_IDS,
       MAX( CASE MAX_RANK WHEN 1 THEN SALARY END ) AS MAX_SALARY
FROM (
  SELECT ID,
         SALARY,
         RANK() OVER ( ORDER BY SALARY  ASC ) AS MIN_RANK,
         RANK() OVER ( ORDER BY SALARY DESC ) AS MAX_RANK
  FROM   C
)

Results

| MIN_SALARY_IDS | MIN_SALARY | MAX_SALARY_IDS | MAX_SALARY |
|----------------|------------|----------------|------------|
|              5 |         90 |            2,4 |        110 |

查询 5

SELECT ID,
       SALARY,
       CASE WHEN MIN_RANK = 1 THEN 'MIN'
            WHEN MAX_RANK = 1 THEN 'MAX' END AS MIN_MAX  
FROM (
  SELECT ID,
         SALARY,
         RANK() OVER ( ORDER BY SALARY  ASC ) AS MIN_RANK,
         RANK() OVER ( ORDER BY SALARY DESC ) AS MAX_RANK
  FROM   C
)
WHERE MIN_RANK = 1 OR MAX_RANK = 1

Results

| ID | SALARY | MIN_MAX |
|----|--------|---------|
|  2 |    110 |     MAX |
|  4 |    110 |     MAX |
|  5 |     90 |     MIN |

【讨论】:

  • 您为什么选择非原子数据作为查询 #4?
  • @JulienBlanchard - 因为最小值和最大值的行数不确定且不相等。
  • 好吧,我更建议有 X 行,每行有 1 个 ID(在这种情况下做 3 行,最多 2 和 1 分钟)。只是为了保持结果的原子性。
  • @JulienBlanchard 当你发表评论时,我只是在更新它来做到这一点。
【解决方案2】:
Select id,
salary 
from C 
where salary = (select MAX(salary) 
                  from C)

【讨论】:

  • + 可能会返回多个不同id但工资相同的记录
  • 如果我想用它添加最小值,它为什么不起作用?
  • @SarahAH 因为您可能使用AND salary = (select MIN(salary) from C 添加了它,而您可以使用OR ... 添加它。如果不是这种情况,我们将需要您向我们展示您所做的事情,以便我们修复它;)
  • @MT0 如果有人问这个问题,那么保持简单可能比表扫描的次数更重要。
  • @JBrooks 我不知道,我认为您不妨指出每种解决方案的优缺点。在这种情况下,一种解决方案更容易编辑(通过更入门级),而另一种解决方案执行得更快。
【解决方案3】:

您可以使用first_valuelast_value

FIRST_VALUE 解析函数类似于 FIRST 解析 函数,允许您从有序集中返回第一个结果。

https://oracle-base.com/articles/misc/first-value-and-last-value-analytic-functions

create table C (id int, salary int);
insert into c values(1, 1);
insert into c values(2, 2);
insert into c values(3, 3);
insert into c values(4, 4);
insert into c values(5, 5);

Select distinct first_value(id) over ( order by salary desc)
from C 

    FIRST_VALUE(ID)OVER(ORDERBYSAL
1   5

【讨论】:

    猜你喜欢
    • 2010-11-15
    • 1970-01-01
    • 2020-10-15
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    相关资源
    最近更新 更多