从多个表和查询中导入事实表数据
Posted
技术标签:
【中文标题】从多个表和查询中导入事实表数据【英文标题】:Import Fact Table Data from Multiple Tables and Queries 【发布时间】:2021-06-06 02:37:23 【问题描述】:我正在尝试在这个雪花模式中构建事实表:!1
我正在使用这个数据库:enter link description here
我正在使用 SSMS,当我右键单击我的仓库并选择导入数据,然后选择查询方法时,我不得不将所有这些查询用于我的度量,并放入我在编写时遇到问题的 1 个大查询中,但最终得到了唯一没有错误的解决方案:
SELECT Orders.OrderID AS OrderID,
Events.EventID AS EventID,
Customers.CustomerID AS CustomerID,
Dishes.DishID AS DishID,
NormAvgTable.AverageNormalCustomerCount,
EveAvgTable.AverageEventCustomerCount,
FavDishTable.CustomerFavDishOrderCount,
EveRevTable.TotalEventsRevenue,
DishOrderCtTable.DishOrderCount,
CustomerRev.CustomerOrderRevenue,
BdayCtTable.CustomerBirthdayOrderCount
FROM Orders, Events, Customers, Dishes
CROSS JOIN (
SELECT AVG(count) AS AverageNormalCustomerCount
FROM (
SELECT Events.EventID, COUNT(Orders.CustomerID) AS count
FROM Customers
INNER JOIN Orders
ON Orders.CustomerID = Customers.CustomerID
INNER JOIN OrdersDishes
ON Orders.OrderID = OrdersDishes.OrderID
INNER JOIN Events
ON CAST(Orders.OrderDate AS DATE) <> CAST(Events.Date AS DATE)
GROUP BY Events.EventID
) AS CtTable
) AS NormAvgTable
CROSS JOIN (
SELECT AVG(count) AS AverageEventCustomerCount
FROM (
SELECT Events.EventID, COUNT(Orders.CustomerID) AS count
FROM Customers
INNER JOIN Orders
ON Orders.CustomerID = Customers.CustomerID
INNER JOIN OrdersDishes
ON Orders.OrderID = OrdersDishes.OrderID
INNER JOIN Events
ON CAST(Orders.OrderDate AS DATE) = CAST(Events.Date AS DATE)
GROUP BY Events.EventID
)AS EveCtTable
) EveAvgTable
CROSS JOIN(
SELECT Customers.CustomerID AS CustomerID, COUNT(Orders.OrderID)
AS CustomerFavDishOrderCount
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID = Customers.CustomerID
INNER JOIN OrdersDishes
ON Customers.FavoriteDish = OrdersDishes.DishID
GROUP BY Customers.CustomerID
) AS FavDishTable
CROSS JOIN (
SELECT SUM(Dishes.Price)
AS TotalEventsRevenue
FROM Events
INNER JOIN Orders
ON CAST(Orders.OrderDate AS DATE) = CAST(Events.Date AS DATE)
INNER JOIN OrdersDishes
ON Orders.OrderID = OrdersDishes.OrderID
INNER JOIN Dishes
ON OrdersDishes.DishID = Dishes.DishID
GROUP BY Events.EventID
) AS EveRevTable
CROSS JOIN(
SELECT Dishes.DishID AS DishID, COUNT(OrdersDishes.OrdersDishesID)
AS DishOrderCount
FROM OrdersDishes
INNER JOIN Dishes
ON Dishes.DishID = OrdersDishes.DishID
GROUP BY Dishes.DishID
) AS DishOrderCtTable
CROSS JOIN(
SELECT Orders.CustomerID AS CustomerID, SUM(Dishes.Price)
AS CustomerOrderRevenue
FROM OrdersDishes
INNER JOIN Orders
ON Orders.OrderID = OrdersDishes.OrderID
INNER JOIN Dishes
ON OrdersDishes.DishID = Dishes.DishID
GROUP BY Orders.CustomerID
) AS CustomerRev
CROSS JOIN(
SELECT Customers.CustomerID AS CustomerID, COUNT(Orders.OrderID)
AS CustomerBirthdayOrderCount
FROM Orders, Customers
WHERE DAY(Orders.OrderDate) = DAY(Customers.Birthday)
AND MONTH(Orders.OrderDate) = MONTH(Customers.Birthday)
GROUP BY Customers.CustomerID
) AS BdayCtTable
除了它看起来很丑之外,它没有给我任何错误,并且一直复制多达 5000 万 条记录,我不得不阻止向导,因为它继续前进。
我可以使用什么更好的查询/如何优化我的查询(其中有什么错误)。
【问题讨论】:
为什么必须在一个查询中完成所有操作? @Charlieface 我正在尝试将链接数据库中的数据导入我使用 SSMS 和 SQL 服务器在图片中提供的雪花模式中,在导入向导中,我似乎只需将所有内容放入 1 个查询中 您在这里使用多个cross join
显然是错误的。我认为你在这里使用cross join
的次数比我在过去 10 年中使用的次数还要多!您的前 4 个表的行全部相乘(这不是编写好的 SQL 的方法),所以如果每个表只有 10 行,那就是 10,000 行。然后将其与随后的交叉连接相乘,其结果乘以下一个交叉连接等。
进化!没有人应该使用old-style joins。更糟糕的是同时使用旧样式和当前样式。
很难从单个查询中构建合适的模式。找到一种导入多个表的方法。我认为您可以多次单击“导入”
【参考方案1】:
两个问题 - 记录数很高,SQL 看起来很复杂/不可读。
由于交叉连接,记录数很高。您需要在子查询和表之间设置一些连接条件。例如,您提到了下表但没有连接 FROM Orders, Events, Customers, Dishes
。我不确定要求,所以这是我的想法/解决方案。 -
-
仅使用 Orders 表创建一个最低限度的 SQL。然后继续添加连接并检查计数,消耗的时间。如果高于预期,请尝试调整该连接。一直到最后一张桌子。
交叉连接总是很昂贵 - 尝试使用内连接或左连接。也很少有表没有产生笛卡尔连接的连接条件,因此结果非常重要。
使用 sqlformat.org/ 让你的 sql 更漂亮:)
如果上面的第 1 点变得复杂,请创建两个 SQL 并创建一个中间表来执行此操作。您不必将所有逻辑都放在一个 SQL 中。也可以打破它。
检查每个表中的索引,看看是否可以在 SQL 中使用它们。
【讨论】:
要求是从链接数据库中构建我在图片中提供的架构!所以我不确定如何将 orderID 与我的其他测量值联系起来,不需要连接,我只是希望所有这些表的结果都在 1 中,但没有重复的行!以上是关于从多个表和查询中导入事实表数据的主要内容,如果未能解决你的问题,请参考以下文章