带日期的Oracle SQL联接
我有以下表格:带日期的Oracle SQL联接,sql,oracle,data-warehouse,Sql,Oracle,Data Warehouse,我有以下表格: Dim\u日期 Dim\u Prod\u Cat Cat提供的事实、产品和销售信息 我有SQL: Select b.date_key, b.day_name_of_week, a.name prod_cat_name, Sum(nvl(a.total_sales,0)) From Dim_Date b Left Outer Join (Select * From Fact_Prod_Sales_
Dim\u日期
Dim\u Prod\u Cat
Cat提供的事实、产品和销售信息
Select b.date_key,
b.day_name_of_week,
a.name prod_cat_name,
Sum(nvl(a.total_sales,0))
From Dim_Date b
Left Outer Join (Select *
From Fact_Prod_Sales_By Cat sa
Inner Join Dim_Prod_Cat c
On sa.prod_cat_key = c.prod_cat_key) a
ON a.date_key = b.date_key
Group By a.name,b.date_key
问题是,若说事实上的周日表并没有销售,那个么我就并没有得到那个只产品猫的记录行
Dim_Date具有5年(前3年和后2年)的所有数据价值
预期:
Prod_Cat Week_Day_Name Sales
-------- ------------- -----------
C1 Monday 1000.00
C1 Tuesday 100.00
...
..
C1 Sunday 0.00 <----
..
..
C2 Monday 1000.00
..
..
C2 Saturday 0.00 <---
C2 Sunday 10000.00
...
..
Prod\u Cat Week\u Day\u Name销售
-------- ------------- -----------
C1星期一1000:00
C1星期二100:00
...
..
C1 Sunday 0.00如果您也能向我们展示每个表格的属性,那就太好了
从这个初学者查询中,我发现一个错误是使用了d
(我认为应该是b
),没有定义d
试着这样做:
SELECT b.date_key, b.day_name_of_week, a.name, SUM(a.tot)
FROM Dim_Date b JOIN
(SELECT c.name, nvl(sa.total_sales,0) AS tot, sa.date_key
FROM Fact_Prod_Sales_By_Cat sa
INNER JOIN Dim_Prod_Cat c ON sa.prod_cat_key = c.prod_cat_key) a
ON a.date_key = b.date_key
GROUP BY a.name,b.date_key;
第二次尝试:
SELECT b.date_key, b.day_name_of_week, a.name, SUM(a.tot)
FROM Dim_Date b JOIN
(SELECT c.name, nvl(sa.total_sales,0) AS tot, sa.date_key
FROM Fact_Prod_Sales_By_Cat sa
LEFT JOIN Dim_Prod_Cat c ON sa.prod_cat_key = c.prod_cat_key
GROUP BY sa.date_key) a
ON a.date_key = b.date_key
GROUP BY a.name,b.date_key;
您的简单聚合查询应该是:
Select d.day_name_of_week,
c.name prod_cat_name,
Sum(f.total_sales)
From Dim_Date d
Join Fact_Prod_Sales_By Cat f ON f.date_key = d.date_key
Join Dim_Prod_Cat c On f.prod_cat_key = c.prod_cat_key
Group By d.day_name_of_week,
c.name prod_cat_name
基于此,为了填补中缺少的天数,您可以在最新的Oracle版本中使用分区外部联接:
Select v.prod_cat_name,
t.day_name_of_week,
Coalesce(v.total_sales,0) total_sales
from (
Select d.day_name_of_week,
c.name prod_cat_name,
Sum(f.total_sales) total_sales
From Dim_Date d
Join Fact_Prod_Sales_By Cat f ON f.date_key = d.date_key
Join Dim_Prod_Cat c On f.prod_cat_key = c.prod_cat_key
Group By d.day_name_of_week,
c.name prod_cat_name) v
partition by (v.prod_cat_name)
right outer join
(select distinct day_name_of_week
FROM dim_date) t
ON (v.day_name_of_week = t.day_name_of_week);
首先,您需要为所有产品类别和日期创建一个笛卡尔产品(使用交叉连接子句完成),然后(左!)将其连接到一个聚合事实表数据,以获得已售出产品的销售额,最后使用NVL函数为非销售组合显示零:
SELECT
d.date_key,
d.day_name_of_week,
pc.name AS prod_cat_name,
NVL(f.total_sales, 0) AS total_sales
FROM
Dim_Date d
CROSS JOIN
Dim_Prod_Cat pc
LEFT JOIN
(
SELECT
date_key,
prod_cat_key,
SUM(total_sales) AS total_sales
FROM
Fact_Prod_Sales_By_Cat
GROUP BY
date_key,
prod_cat_key
) f
ON
d.date_key = f.date_key
AND
pc.prod_cat_key = f.prod_cat_key;
你查过那张桌子上有星期天吗?如果是这样的话,我看到甲骨文搞砸了,使用他们自己的语法“(+)”而不是ansi join。我将回答编辑成疑问:你想看到(I)dim_date表中包含的每个日期,还是(ii)任何类别下都有销售的每个日期,或者(iii)所有类别的第一个和最后一个销售日期之间的每个日期?还有,您的Oracle版本是什么?如果没有表属性,我认为您的问题是您应该在内部表a
中使用nvl(total_sales,0)
。通过这种方式,您不再需要左联接
,因为表a
中没有空值
。问题是,事实表中可能没有某些日期的记录。您可以制作一个SQLFIDLE以便我可以测试查询吗?我理解你的陈述。@gpa检查我写的第二个查询。我认为这条路可能是对的。