【问题标题】:SQL to map max and min in one row, next max and next min in the next row, and so onSQL 在一行中映射最大值和最小值,在下一行中映射下一个最大值和下一个最小值,依此类推
【发布时间】:2021-12-08 21:51:13
【问题描述】:

这是一个例子:

表格

Name Salary
A 1000
B 500
C 400
D 100

输出

Name salary_highest name salary_Lowest
A 1000 D 100
B 500 C 400

因此,最高和最低工资应该被映射并出现在一行中,并且输出应该是多行而不是映射高低工资的单行,直到表的数据结束。

我能够得到最大值和最小值,第二个最大值和第二个最小值等等,一次只能得到一行,但这不是我想要的。

我们可以使用的任何循环。 我正在使用 MySQL - mycompiler.io 在线编译器。

更新: 我试过这种方式-

Select E1.salary as MIN, E2.salary as MAX
from employees E1, employees E2 where
E1.salary < (select max(salary) from employees) and 
E2.salary < (select min(salary) from employees);

得到了这个输出-

输出

MIN MAX
500 1000
400 1000
100 1000
500 500
400 500
100 500
500 400
400 400
100 400

猜猜循环工作,但所有额外的记录都得走了,输出应该是-

MIN MAX
100 1000
400 500

列表中存在的。我哪里错了

【问题讨论】:

  • 如果行数为奇数会怎样?工资有关系吗?
  • select version() 显示什么?
  • 考虑添加更好的样本数据和Minimal, Reproducible Example,因为它有太多的歧义和场景没有涵盖。您还应该包括到目前为止您的最佳尝试以及您卡在哪里。
  • 如果我理解正确,你想要做的基本上是:得到 both MAX(salary)MIN(salary) 以及正确的 name,然后重新使用相同的查询并排除之前的结果?
  • 枚举行 asc 和 desc 然后通过 t1.n_asc+t2.n_desc=count+1 将它们组合(连接 2 个副本)成对。

标签: mysql sql max min


【解决方案1】:

您可以在一个公用表表达式中计算升序和降序,然后将其自联接:

with ranked_employees as (
    select name, salary,
        row_number() over w_asc row_asc,
        row_number() over w_desc row_desc
    from employees
    window
        w_asc as (order by salary, id),
        w_desc as (order by salary desc, id desc)
)
select d.name, d.salary, a.name, a.salary
from ranked_employees d
inner join ranked_employees a on a.row_asc=d.row_desc and d.row_asc >= d.row_desc

d.row_asc &gt;= d.row_desc 条件使它停在中点。

请注意,您需要对 id 或其他一些唯一字段以及薪水进行排序,以确保升序和降序计数之间的顺序一致。

【讨论】:

    【解决方案2】:

    快速回答:

    SELECT
      tdesc.name AS highname,
      tdesc.salary AS hightsalary,
      tasc.name AS lowname,
      tasc.salary AS lowsalary
    FROM (
      SELECT
        ROW_NUMBER() OVER (ORBER BY salary, name) rank1,
        name,
        salary
      FROM table
      ORDER BY salary, name ASC
    ) AS tasc
    INNER JOIN (
      SELECT
        ROW_NUMBER() OVER (ORDER BY salary, name) rank2,
        name,
        salary
      FROM table
      ORDER BY salary, name DESC
    ) AS tdesc
    ON tdesc.rank2 = tasc.rank1
    WHERE tdesc.salary >= tasc.salary
    

    解释:

    正如@akina 评论的那样,我们希望以相反的顺序加入 base 表的副本:

    为此,我们首先声明2个row counters:rank1和rank2。

    编辑:MySQL 支持ROW_NUMBER 函数,可以实现相同的目的。

    第一个子查询创建一个临时表 tasc,其中包含 base 表中的所有值以及“订单 ID”,按工资 ASC 排序。

    任务

    rank1 name salary
    1 A 1000
    2 B 500
    3 C 400
    4 D 100

    第二个子查询将执行相同的操作,但顺序相反。

    tdesc

    rank2 name salary
    1 D 100
    2 C 400
    3 B 500
    4 A 1000

    现在,我们使用一些别名加入 tasc.rank1 = tdesc.rank2 上的表。

    加入表

    highname highsalary lowname lowsalary
    A 1000 D 100
    B 500 C 400
    C 400 B 500
    D 100 A 1000

    如您所见,现在所有行都重复了,后半部分也有不相关的值,我们必须使用 where 条件 WHERE tdesc.salary &gt;= tasc.salary 将其过滤掉。

    最终结果

    highname highsalary lowname lowsalary
    A 1000 D 100
    B 500 C 400

    在奇数行的情况下

    &gt;= where 子句中的 或等于 将确保您不会丢失数据,结果的最后一行将包含 中位数的两倍数据 em> 薪水。

    highname highsalary lowname lowsalary
    A 1000 D 100
    B 500 C 400
    E 450 E 450

    多人同薪的情况

    或等于将再次确保您不会丢失任何数据。此外,ORDER BY salary, name 将确保您在行中有不同的名称:

    highname highsalary lowname lowsalary
    A 1000 D 100
    B 500 C 400
    E 450 F 450

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 2015-01-09
      • 2015-02-03
      • 2022-01-18
      • 2019-07-13
      • 2012-03-20
      • 2021-09-10
      • 1970-01-01
      相关资源
      最近更新 更多