Oracle通过带有内部连接和返回n行的子查询的桥表选择查询?
Posted
技术标签:
【中文标题】Oracle通过带有内部连接和返回n行的子查询的桥表选择查询?【英文标题】:Oracle select query via bridge table with inner joins and subquery that returns n number of rows? 【发布时间】:2018-01-23 21:20:36 【问题描述】:我开发了一个遵循星型模式的数据仓库。在这个模式中,我有多个维度表连接到我的事实表。但是,我在这些维度之一和事实表之间有一个桥接表。
即我的仓库架构示例
产品
Fact table contains: ProductGroup_SK...
ProductGroup table contains: ProductGroup_SK, Product_SK
Product table contains: Product_SK, product_fields...
我将使用 Oracle Data Miner 对我的数据仓库进行分析,并且一直在尝试根据连接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 个。
基本上,我希望找到一种方法来获得与我上面所做的这种 hack 方式相同的结果,即结果而不是看起来像这样:
... 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 ........... .......... ..........
我在上面演示的查询产生了这个期望的结果,但正如您所见,它不是好的代码,并且对于包含少于或多于两个产品的 productGroups 是不切实际的。
任何建议都将不胜感激,我一直在尝试弄清楚如何正确执行此操作,但找不到通过一行中的桥接表读取数据的任何好的示例。这可能吗?
【问题讨论】:
使用这种设计,您将永远无法在产品级别看到销售/订单/whatever-the-fact-table-measures。是这个意图吗?示例:Fact 对第 1 组有 1 笔销售。组中有 3 种产品:苹果、香蕉和草莓。你卖了多少草莓? 我知道你在说什么,但是在产品表中我将有产品相关的字段,如类别、生产者等。它不会影响事实表中的度量,纯粹是为了获取每个产品的信息(不是每个产品的销售) 我的设计可能吗?我不需要每个产品的事实表中的特定度量,我只是希望在我加入其他各种维度之后将每个 productGroup 中的项目扩展为一个查询结果,并希望所有产品都显示在一个查询结果行。 有固定上限吗?或者一个组可以包含任意数量的产品? 【参考方案1】:我认为你只需要不同的表别名:
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;
【讨论】:
感谢您的回复!但是,我使用 min 和 max 的方式只是一种技巧,这对于其中只有 1 个产品或 6 个产品的产品组不起作用,因为这只会显示 2 个产品,不是吗?抱歉,我的问题可能很混乱..【参考方案2】:鉴于需要产品名称或产品描述来为产品组提供上下文,当与事实结合时,也许这种方法可以工作。
我将其用作参考 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;
【讨论】:
以上是关于Oracle通过带有内部连接和返回n行的子查询的桥表选择查询?的主要内容,如果未能解决你的问题,请参考以下文章