什么是`SELECT ...,(SELECT ... FROM ...)FROM(SELECT ... FROM(SELECT ... FROM ...))`构造类型的最佳替代方法?

时间:2015-12-17 13:39:47

标签: sql oracle

我写了这个查询。但是,我想知道是否有更好/专业的方法来重写这个。

  

找到将在当年获得奖金的员工。获得奖金的条件是,他必须出售至少4000美元的特定类别的产品。

[[ -s "$HOME/.profile" ]] && source "$HOME/.profile" # Load the default .profile

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

编辑:表架构:

select yy.CurrentMonth, yy.ID, yy.Name, sum(yy.commission) as comm_total, sum(yy.bonus) as bonus_total
from
(select sysdate as CurrentMonth, ee.ID, ee.Name, cc.commission, (cc.commission * 25 / 100) as bonus
from employee ee,
(select e.id, pc.category_name, sum(quantity) as qty, pc.commission_rate, sum(quantity*pc.commission_rate) as commission
from sales s, product p, product_category pc, employee e
where to_char(sales_date, 'yyyy') = to_char(sysdate, 'yyyy')
and s.employee_id = e.id
and s.product_id = p.id
and p.product_category_name = pc.category_name
group by pc.category_name, e.id, pc.commission_rate
order by e.id) cc
where ee.ID = cc.id
and cc.commission >=4000
) yy
group by yy.ID, yy.Name, yy.CurrentMonth

2 个答案:

答案 0 :(得分:2)

您可以使用多步cte,使用indenation,使用JOIN语法,避免长行,大写关键字,避免在子查询中排序等等:

WITH cte AS 
(
  SELECT e.id
        ,pc.category_name
        ,pc.commission_rate
        ,SUM(quantity)                      AS qty
        ,SUM(quantity * pc.commission_rate) AS commission
  FROM sales s
  JOIN product p
    ON s.product_id = p.id
  JOIN product_category pc
    ON p.product_category_name = pc.category_name
  JOIN employee e
    ON s.employee_id = e.id
  WHERE TO_CHAR(sales_date, 'yyyy') = TO_CHAR(SYSDATE, 'yyyy')
  GROUP BY e.id, pc.category_name, pc.commission_rate
), cte2 AS 
(
  SELECT SYSDATE AS CurrentMonth
        ,ee.ID
        ,ee.Name
        ,cc.commission
        ,(cc.commission * 25 / 100) AS bonus
  FROM cte cc
  JOIN employee ee
    ON ee.ID = cc.id
  WHERE cc.commission >= 4000
)
SELECT CurrentMonth
      ,ID
      ,Name
      ,SUM(commission) AS comm_total
      ,SUM(bonus)      AS bonus_total
FROM cte2 
GROUP BY CurrentMonth, ID, Name;

答案 1 :(得分:2)

我相信您不需要额外加入员工表 - 您只是想要排除总计佣金的行数<&lt; 4000,对吗?如果是这样,您可以使用having子句通过查询轻松地在组中执行此操作,例如:

with sum_categories as (select   e.id,
                                 e.name,
                                 pc.category_name,
                                 sum(s.quantity) as qty,
                                 pc.commission_rate,
                                 sum(s.quantity * pc.commission_rate) as commission
                        from     sales s
                                 inner join product p on (s.product_id = p.id)
                                 inner join product_category pc on (p.product_category_name = pc.category_name)
                                 inner join employee e on (s.employee_id = e.id)
                        where    trunc(sales_date, 'yyyy') = trunc(sysdate, 'yyyy')
                        group by pc.category_name,
                                 e.id,
                                 e.name,
                                 pc.commission_rate
                        having   sum (quantity * pc.commission_rate) >= 4000)
select   sysdate currentmonth, -- should this be trunc(sysdate, 'mm')?
         yy.id,
         yy.name,
         sum (yy.commission) as comm_total,
         sum (yy.commission * 25 / 100) as bonus_total
from     sum_categories yy
group by yy.id,
         yy.name;

您注意我已将to_char(sales_date, 'yyyy') = to_char(sysdate, 'yyyy')更改为trunc(sales_date, 'yyyy') = trunc(sysdate, 'yyyy'),因为我更愿意在正确的数据类型之间进行比较(您要比较两个日期,所以我想保留他们作为约会)。