在销售时获得购买价格

时间:2016-10-25 13:51:10

标签: sql oracle

我试图在销售时获得购买价格。我桌上的同一产品有不同的购买价格。

购买价格由两个日期定义。有效期开始的一个日期和有效期结束的另一个日期:DATE_DEB_VALID和DATE_FIN_VALID。

如果我想知道我在销售时赢得了多少(FLIGHT_DATE),我必须知道同期的购买价格。 我的航班日期必须介于“DATE_DEB_VALID”和“DATE_FIN_VALID”之间

两个表:

TB_DW_VAB_SALES     

 - ID_TEC_SALES 
 - TRANSACTION_NUMBER 
 - CARRIER_CODE 
 - MASTER_FLIGHT_NUMBER
 - FLIGHT_NUMBER 
 - FLIGHT_DATE
 - FLIGHT_CITY_DEP 
 - FLIGHT_CITY_ARR
 - PRODUCT_CODE 
 - QUANTITY
 - UNIT_SALES_PRICE
 - PROMOTION_CODE
 - CREW_PRICE 
 - COMPLEMENTARY 
 - SALES_TYPE 
 - DATE_CHGT

TB_DW_VAB_PURCHASE 

     - PRODUCT_CODE  
     - PRODUCT_CODE_GUEST 
     - LIB_PRODUCT 
     - PRICE DATE_DEB_VALID
     - DATE_FIN_VALID 
     - DATE_CHGT

我的要求:

SELECT (TB_DW_VAB_PURCHASE.PRODUCT_CODE),PRICE 
       FROM TB_DW_VAB_PURCHASE,TB_DW_VAB_SALES 
       WHERE FLIGHT_DATE BETWEEN DATE_DEB_VALID AND DATE_FIN_VALID AND to_char(FLIGHT_DATE,'YYYY')= '2016' OR to_char(FLIGHT_DATE,'YYYY')= '2015'
       GROUP BY TB_DW_VAB_PURCHASE.PRODUCT_CODE, PRICE

这里我们有完整的请求(信息):

SELECT  to_char(DATE_VENTE,'MM/YYYY'),sum(MARGE_TOTALE) FROM (
    SELECT 
          CTE1.CA AS CHIFFRE_AFFAIRE_TOTAL,
          CTE2.PRICE AS COUT_UNITAIRE,
          CTE1.FLIGHT_DATE as DATE_VENTE,
          CTE1.QTE*CTE2.PRICE AS COUT_ACHAT,
          (CTE1.CA-CTE1.QTE*CTE2.PRICE) AS MARGE,
          sum((CTE1.CA-CTE1.QTE*CTE2.PRICE)) as MARGE_TOTALE
    FROM (
        SELECT PRODUCT_CODE,
         sum(QUANTITY*UNIT_SALES_PRICE) AS CA,
         FLIGHT_DATE,
         sum(QUANTITY) as QTE
        FROM TB_DW_VAB_SALES
        where SALES_TYPE = 'SALES' and to_char(FLIGHT_DATE,'YYYY')= '2015' OR  to_char(FLIGHT_DATE,'YYYY')= '2016'
        group by to_char(FLIGHT_DATE,'MM'),FLIGHT_DATE,PRODUCT_CODE
        ORDER BY to_char(FLIGHT_DATE,'MM') ASC
      )CTE1

 inner join 
    (
       SELECT (TB_DW_VAB_PURCHASE.PRODUCT_CODE),PRICE 
       FROM TB_DW_VAB_PURCHASE,TB_DW_VAB_SALES 
       WHERE FLIGHT_DATE BETWEEN DATE_DEB_VALID AND DATE_FIN_VALID AND to_char(FLIGHT_DATE,'YYYY')= '2016' OR to_char(FLIGHT_DATE,'YYYY')= '2015'
       GROUP BY TB_DW_VAB_PURCHASE.PRODUCT_CODE, PRICE
    ) CTE2 
on CTE1.PRODUCT_CODE=CTE2.PRODUCT_CODE 
group by to_char(FLIGHT_DATE,'MM'), FLIGHT_DATE, 'MM', CTE1.FLIGHT_DATE, (CTE1.CA-CTE1.QTE*CTE2.PRICE), 
CTE1.CA, CTE1.QTE, CTE2.PRICE, CTE1.QTE*CTE2.PRICE

) group by to_char(DATE_VENTE,'MM/YYYY') ORDER BY to_char(DATE_VENTE,'MM/YYYY') ASC;

谢谢!

2 个答案:

答案 0 :(得分:2)

我会修复你的初始查询,直到你忘记你的基本代数(并且优先于OR):

SELECT (TB_DW_VAB_PURCHASE.PRODUCT_CODE),PRICE 
FROM TB_DW_VAB_PURCHASE,TB_DW_VAB_SALES 
WHERE FLIGHT_DATE BETWEEN DATE_DEB_VALID AND DATE_FIN_VALID AND 
 (to_char(FLIGHT_DATE,'YYYY')= '2016' OR to_char(FLIGHT_DATE,'YYYY')= '2015')
GROUP BY TB_DW_VAB_PURCHASE.PRODUCT_CODE, PRICE

现在如果你使用了规范化连接,你也会看到你忘记了product_code上的join子句,所以最后:

SELECT PUR.PRODUCT_CODE, PRICE 
FROM TB_DW_VAB_PURCHASE PUR
inner join TB_DW_VAB_SALES SAL ON PUR.PRODUCT_CODE = PUR.PRODUCT_CODE 
  AND FLIGHT_DATE BETWEEN DATE_DEB_VALID AND DATE_FIN_VALID 
WHERE to_char(FLIGHT_DATE,'YYYY')= '2016' OR to_char(FLIGHT_DATE,'YYYY')= '2015'
GROUP BY PUR.PRODUCT_CODE, PRICE

答案 1 :(得分:2)

正如Nemeros已经指出的那样,您在CTE2子查询中有一个交叉加入,因为您没有将销售和购买链接在一起 - 除了航班/有效日期,而是在所有产品中,这可能不是你想要的。

看起来你正在计算内联视图中的内容(命名它们CTE1 / 2有点令人困惑,因为它通常是指公用表表达式或子查询因子分析),然后你将其用于进一步的计算,但我不是&# 39;认为需要中间步骤或值。

它(看起来像你的查询可以简化为:

select to_char(trunc(s.flight_date, 'MM'),'MM/YYYY') as mois_du_sales,
  sum(s.quantity*(s.unit_sales_price - p.price)) as marge_totale
from tb_dw_vab_sales s
join tb_dw_vab_purchase p
on p.product_code = s.product_code
and s.flight_date between p.date_deb_valid and p.date_fin_valid
where s.sales_type = 'SALES'
and s.flight_date >= date '2015-01-01'
and s.flight_date < date '2017-01-01'
group by trunc(s.flight_date, 'MM')
order by trunc(s.flight_date, 'MM') asc;

当然,如果没有样本数据或预期结果,我无法验证我是否正确解释了它。它也可能无法解决您的所有性能问题 - 您仍需要查看表和索引以及执行计划以查看它实际执行的操作,如果您的数据量很大,您可能需要考虑分区数据和方便的分区键(如销售年度)。

使用像to_char(FLIGHT_DATE,'YYYY')= '2015'这样的过滤器强制该列中的每个值(或者至少匹配sales_type的那些值,如果它已被索引并且有足够的选择性)转换为字符串然后与固定的数据进行比较值 - 两次分别检查两年 - 并停止使用flight_date上的任何索引。使用日期范围允许使用索引,但除非您有多年的数据,否则它可能仍然没有足够的选择性,并且优化器仍可选择全表扫描。但每张桌子只有一张,而不是你可能做的两张。