带日期的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提供的事实、产品和销售信息
  • 我有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_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检查我写的第二个查询。我认为这条路可能是对的。