我试图在销售时获得购买价格。我桌上的同一产品有不同的购买价格。
购买价格由两个日期定义。有效期开始的一个日期和有效期结束的另一个日期: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;
谢谢!
答案 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
上的任何索引。使用日期范围允许使用索引,但除非您有多年的数据,否则它可能仍然没有足够的选择性,并且优化器仍可选择全表扫描。但每张桌子只有一张,而不是你可能做的两张。