Oracle通过桥接表选择查询,内部连接和返回n行的子查询?

时间:2018-01-23 21:20:36

标签: sql oracle join pivot data-warehouse

我开发了一个遵循星型模式的数据仓库。在这个模式中,我有多个维度表连接到我的事实表。但是,我在其中一个维度和事实表之间有一个桥接表。

即。我的仓库架构的示例

产品< - ProductGroup< - Fact

Fact table contains: ProductGroup_SK...
ProductGroup table contains: ProductGroup_SK, Product_SK
Product table contains: Product_SK, product_fields...

我将使用Oracle Data Miner对我的数据仓库进行分析,并且一直在尝试确定如何为每个事实返回一行,包含产品表中的产品详细信息,基于连接的ProductGroup_SK事件表到ProductGroup桥表。

到目前为止,我已经能够成功加入并返回一行,但这只有在productGroup中只有两个产品时才有效。此外,如果组中只存在一个产品,则此查询将返回相同的产品两次,因为我使用MIN和MAX在查询中指定了两个连接。

Select * from Fact f
join Product p ON p.Product_SK = (SELECT MIN(Product_SK) FROM ProductGroup pg WHERE pg.ProductGroup_SK = f.ProductGroup_SK)
join Product p ON p.Product_SK = (SELECT MAX(Product_SK) FROM ProductGroup pg WHERE pg.ProductGroup_SK = f.ProductGroup_SK);

我已经读过这里应该使用PIVOT查询,但我不需要执行任何聚合,并且每个productGroup中的行数对于事实表中的每一行都不会相同,即某些组可能有只有1个产品,有些可能有6个。

基本上我希望找到一种方法来获得与我上面所做的这种黑客方式相同的结果,即结果而不是看起来像这样:

... ProductGroup_SK   Product_SK   Product_Name   Product_Category .. etc
           123            1           Apple           Fruit
           123            2           Banana          Fruit

应该是这样的:

... ProductGroup_SK   Product_SK   Product_Name   Product_Category   Product_SK_1   Product_Name_1   Product_Category_1 .. Product_SK_N   Product_Name_N   Product_Category_N
           123            1           Apple           Fruit                 2           Banana          Fruit               ...........      ..........      ..........

我在上面演示的查询产生了所需的结果,但正如您所看到的那样,它不是一个好的代码,对于包含少于或多于两个产品的productGroup来说是不切实际的。

任何建议都会非常感激,我一直试图弄清楚如何正确地做到这一点,但找不到通过一排桥表读取数据的任何好例子。这可能吗?

2 个答案:

答案 0 :(得分:0)

我认为你只需要不同的表别名:

Select f.*, pmin.*, pmax.*
from Fact f join
     Product pmin
     on pmin.Product_SK = (SELECT MIN(Product_SK)
                           FROM ProductGroup pg
                           WHERE pg.ProductGroup_SK = f.ProductGroup_SK
                          ) join
     Product pmax
     ON pmax.Product_SK = (SELECT MAX(Product_SK)
                           FROM ProductGroup pg
                           WHERE pg.ProductGroup_SK = f.ProductGroup_SK
                          );

但这绝对不是我写这个查询的方式。 FROM子句中的子查询只是令人困惑。代替:

Select f.*, pmin.*, pmax.*
from Fact f join
     (select pg.ProductGroup_SK, max(pg.Product_SK) as maxp, min(pg.Product_SK) as minp
      from ProductGroup pg
      group by pg.ProductGroup_SK
     ) pg
     on pg.ProductGroup_SK = f.ProductGroup_SK join
     Product pmin
     on pmin.Product_SK = pg.minp join 
     Product pmax
     on pmax.Product_SK = pg.maxp;

答案 1 :(得分:0)

鉴于产品名称或产品描述在与事实相结合时需要为产品组提供上下文,那么这种方法可能也可行。

我使用此作为参考SQL Query to concatenate column values from multiple rows in Oracle来生成以下查询。

/* Step 1: Join Product & Product Group table 
   Step 2: Concatenate Product Names grouped by Product Group on the table retuned from step1.  The Grain of this result table should be same as the product_group dimension.
   Step 3: Joined the result table from step 2 with the fact table */



-- Step 3
Select * 
from fact, 
     -- Step 2:
     (      
    Select  
            product_group_sk,
            LISTAGG(product_name, ', ') WITHIN GROUP (ORDER BY product_group_sk) AS product_name                
        from 
         -- Step 1
         ( 
            Select product_group_sk, 
                   Product_sk, 
                   product_name                
            from product_group pg, product p
            where pg.product_sk = p.product_sk) product_group_list
        group by product_group_list.product_group_sk
    ) product_group_pivoted_list
Where fact.product_group_sk = product_group_pivoted_list.product_group_sk;