【问题标题】:how to express DENSE_RANK with ANSI SQL?如何用 ANSI SQL 表示 DENSE_RANK?
【发布时间】:2013-12-21 03:12:39
【问题描述】:

下面的语句可以用ANSI SQL来表达吗?因为下面的例子属于 PL/SQL。提前致谢。

SELECT department_id,
MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct) "Worst",
MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct) "Best"
   FROM employees
   GROUP BY department_id;

DEPARTMENT_ID      Worst       Best
------------- ---------- ----------
           10       4400       4400
           20       6000      13000
           30       2500      11000
           40       6500       6500
           50       2100       8200
           60       4200       9000
           70      10000      10000
           80       6100      14000
           90      17000      24000
          100       6900      12000
          110       8300      12000
                    7000       7000

【问题讨论】:

  • 这个例子直接来自documentation。你到底想做什么或理解什么?

标签: sql oracle plsql ansi-sql


【解决方案1】:

在大多数情况下,您可以使用自联接而不是分析。这里相当于你的MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct)

SELECT department_id, MAX(salary)
  FROM employees e
 WHERE (department_id, commission_pct) IN
       (SELECT department_id, 
               MAX(commission_pct) 
          FROM employees 
         GROUP BY department_id)
 GROUP BY department_id

显然,同时获得MAXMIN 会有点棘手(也更丑陋),但也是可行的。

【讨论】:

  • Vince,只是想知道您为什么使用这种格式而不是传统的连接语法?
  • @Hogan 它们在逻辑上是相同的,但是我发现自加入最好理解为一个过滤器:“佣金最高的员工”。过滤器最好放在 where 子句中。此外,更容易立即看出这样的条件不会增加行数(而连接可以增加行数)。
【解决方案2】:

考虑到这一点,我会尝试一下。我认为您正在尝试使用 ANSI SQL 显示每个组(deptid)的最高和最低值(示例中的薪水)?这是一个超级简单的示例(使用 DENSE_RANK()),它应该适用于任何符合 ANSI 的数据库:

SQL FIddle
select
    t1.deptid,
    t1.salary as Highest,
    t2.salary as Lowest
from
    (
    select
        deptid,
        salary,
        dense_rank() over (partition by deptid order by salary desc) as First  --rank desc for highest
    from
        salaries
    ) T1
inner join 
    (
    select
        deptid,
        salary,
        dense_rank() over (partition by deptid order by salary asc) as worst -- rank ascending for lowest
    from
        salaries
    )T2
on 
    t1.deptid = t2.deptid

where
    t1.first = 1  --GET THE HIGHEST SALARY
    and t2.worst = 1 -- GET THE LOWEST

使用minmax 也可以,而且简单得多:

Another SQL Fiddle
select
  deptid,
  max(salary) as Highest,
  min(salary) as Lowest
from
  salaries
group by
  deptid

【讨论】:

  • 查看文森特对霍根回答的评论。 “普通” group by 不是这样做的。
【解决方案3】:

这种结构避免了对雇员表的额外连接。在 ANSI SQL 中,您必须首先查询每个部门的最高佣金百分比,然后(再次)加入员工以查找具有最高佣金百分比的薪水

在 ANSI SQL 中,它会是这样的:

select * from
(
  SELECT department_id,
   MIN(commission_pct) max_c
   MAX(commission_pct) min_c
  FROM employees
  GROUP BY department_id
) e1 
join employees e2 
  on (e1.department_id = e2.department_id and e1.max_c = e2.commission_pct)
join employees e3 
  on (e1.department_id = e3.department_id and e1.min_c = e3.commission_pct)

即使这也不是 100% 正确的。

【讨论】:

    【解决方案4】:

    这会返回相同的结果(据我所知),但不需要连接并且是 ANSI SQL:

    select department_id,
           min(case when min_comm = 1 then salary end) as worst,
           max(case when max_comm = 1 then salary end) as best
    from (
      select department_id, 
             salary, 
             dense_rank() over (partition by department_id order by commission_pct desc) as max_comm,
             dense_rank() over (partition by department_id order by commission_pct) as min_comm
      from employees
    ) t
    group  by department_id
    order by 1;
    

    【讨论】:

      猜你喜欢
      • 2017-12-26
      • 2019-11-14
      • 2017-11-15
      • 1970-01-01
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多