#sql #sql-server #data-warehouse
Вопрос:
Я пытаюсь построить таблицу фактов в этой схеме снежинки: !1
Я использую эту базу данных: введите описание ссылки здесь
Я использую 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
Помимо того, что он выглядит очень уродливо, он не давал мне ошибок и продолжал копировать до 50 миллионов записей, на чем мне пришлось остановить мастера, потому что он продолжал идти еще дальше.
Какой лучший запрос я могу использовать/как оптимизировать свой (какие в нем ошибки).
Комментарии:
1. Почему вы должны делать все это в одном запросе?
2. @Charlieface я пытаюсь импортировать данные из связанной базы данных в схему snowflake, которую я предоставил на картинке, используя SSMS и SQL server, в мастере импорта, похоже, мне нужно поместить все только в 1 запрос
3. Ваше использование множественного
cross join
числа здесь явно неправильно. Я думаю, что вы пользовалисьcross join
здесь больше раз, чем я за последние 10 лет! Все строки ваших первых 4 таблиц умножаются вместе (это НЕ то, как писать хороший SQL), поэтому, если бы в каждой было только по 10 строк, это сразу 10 000 строк. Затем это умножается на последующее перекрестное соединение, результат которого умножается на следующее перекрестное соединение и т.д.4. Эволюционируй! Никто не должен использовать соединения старого стиля . Хуже всего использование как старых, так и современных стилей.
5. Будет трудно построить правильную схему на основе одного запроса. Найдите способ импорта нескольких таблиц. Вы можете просто нажать «импортировать» несколько раз, я думаю
Ответ №1:
Две проблемы — высокое количество записей и SQL выглядит сложным/нечитаемым. Количество записей велико из-за перекрестного соединения. Вам нужно установить некоторое условие соединения между подзапросами и таблицами. Например, вы упомянули нижеприведенные таблицы, но никаких соединений FROM Orders, Events, Customers, Dishes
. Я не уверен в требованиях, поэтому вот мои мысли/решения. —
- Сделайте минимальный SQL только с таблицей заказов. Затем продолжайте добавлять соединения и проверяйте количество, затраченное время. если выше ожиданий, попробуйте настроить это соединение. продолжайте до последнего столика.
- Перекрестное соединение всегда дорого — попробуйте использовать внутреннее или левое. Кроме того, в немногих таблицах нет условий соединения, которые приводят к декартову соединению и, таким образом, увеличивают количество результатов.
- Использовать sqlformat.org/ чтобы сделать ваш sql красивым 🙂
- Если пункт № 1 выше становится сложным, создайте два SQLS и создайте для этого промежуточную таблицу. Вам не нужно помещать всю логику в один SQL. Может и его сломать.
- Проверьте индекс в каждой таблице и посмотрите, можете ли вы использовать их в своем SQL.
Комментарии:
1. требование состоит в том, чтобы построить схему, которую я предоставил на картинке, из связанной базы данных! поэтому я не уверен, как связать OrderID, например, с другими моими измерениями, соединение не требуется, и я просто хотел, чтобы результат всех этих таблиц был в 1, но без повторяющихся строк!