У меня есть вопрос. На основе моих фиктивных данных я хотел бы создать представление, которое
DIM_CUSTOMER
DECLARE @DIM_CUSTOMERS TABLE([BusinessKey] INT,[Customer] NVARCHAR(255))
INSERT INTO @DIM_CUSTOMERS
VALUES
(10000, 'Kevin N.V.'),
(10001, 'V.Z.W. Frederik'),
(10002, 'Klaas N.V.')
SELECT * FROM @DIM_CUSTOMERS
DIM_PRODUCT
DECLARE @DIM_PRODUCTS TABLE([BusinessKey] INT, [Product] NVARCHAR(255))
INSERT INTO @DIM_PRODUCTS
VALUES
(9000, 'PH114'),
(9001, 'PH272'),
(9002, 'PH878')
SELECT * FROM @DIM_PRODUCTS
DIM_DATES
DECLARE @DIM_DATES TABLE([BusinessKey] INT, [Year] INT, [Month] INT, [YearMonth] INT, [YearMonthText] NVARCHAR(20))
INSERT INTO @DIM_DATES
VALUES
(202301, 2023, 1, 202301, '2023.01'),
(202302, 2023, 2, 202302, '2023.02'),
(202303, 2023, 3, 202303, '2023.03'),
(202304, 2023, 4, 202304, '2023.04'),
(202305, 2023, 5, 202305, '2023.05'),
(202306, 2023, 6, 202306, '2023.06'),
(202307, 2023, 7, 202307, '2023.07'),
(202308, 2023, 8, 202308, '2023.08'),
(202309, 2023, 9, 202309, '2023.09'),
(202310, 2023, 10, 202310, '2023.10'),
(202311, 2023, 11, 202311, '2023.11'),
(202312, 2023, 12, 202312, '2023.12'),
(202401, 2024, 1, 202401, '2024.01'),
(202402, 2024, 2, 202402, '2024.02'),
(202403, 2024, 3, 202403, '2024.03'),
(202404, 2024, 4, 202404, '2024.04'),
(202405, 2024, 5, 202405, '2024.05'),
(202406, 2024, 6, 202406, '2024.06'),
(202407, 2024, 7, 202407, '2024.07'),
(202408, 2024, 8, 202408, '2024.08'),
(202409, 2024, 9, 202409, '2024.09'),
(202410, 2024, 10, 202410, '2024.10'),
(202411, 2024, 11, 202411, '2024.11'),
(202412, 2024, 12, 202412, '2024.12')
SELECT * FROM @DIM_DATES
ФАКТ_ПРОДАЖИ
DECLARE @FACT_SALES TABLE([ID] INT, [FK_Product] INT, [FK_Customer] INT, [FK_Date] INT, [Sales] FLOAT)
INSERT INTO @FACT_SALES
VALUES
(1, 9000, 10000, 202303, 90.48),
(2, 9000, 10000, 202304, 20.40),
(3, 9002, 10000, 202305, 250.85),
(4, 9002, 10000, 202303, 100.50),
(5, 9000, 10000, 202403, 38.40),
(6, 9000, 10000, 202406, 474.50),
(7, 9001, 10000, 202403, 128.60),
(8, 9001, 10000, 202404, 144.97),
(9, 9000, 10002, 202303, 199.60),
(10, 9001, 10002, 202302, 58.97),
(11, 9001, 10002, 202402, 40.88)
SELECT * FROM @FACT_SALES
Это пример того, что я хочу, на мой взгляд:
| Customer | Product | YearMonthText | Sales |
| ------------------------- | --------------------- | --------------------- | --------------------- |
| Kevin N.V. | PH114 | 202301 | 0 |
| Kevin N.V. | PH114 | 202302 | 0 |
| Kevin N.V. | PH114 | 202303 | 90 |
Когда я воссоздаю обычное представление, я вижу только данные, которые были проданы за этот конкретный год/месяц. Мне удалось сделать это в Power BI с DAX (ALLSELECTED), но я хочу сделать то же самое в SQL Server для повышения производительности. Я попытался создать что-то в T-SQL, чтобы начать с таблицы клиентов или использовать CROSS JOINS, но не удалось получить результаты.
Может ли кто-нибудь помочь мне с этой проблемой?
Спасибо!
Пожалуйста, покажите (в виде уценки таблицы) желаемые результаты и покажите нам свою попытку.
Я специально сказал, что данные должны быть в уценке таблицы, а не в виде изображения - это правило сайта, а не мое.





Проверьте эту скрипку, чтобы увидеть это в действии. Это не самое элегантное решение, но оно работает.
При этом используется пара CTE для
CustProdYears Получите уникальный список клиентов, продуктов и лет, чтобы мы могли ограничить результаты только этими клиентами, продуктами и годами. Это сделано для того, чтобы год не появлялся, если клиент не продал определенный продукт в этом году.
CustomerSales Получите список всех продаж, в которых клиент, продукт и год указаны в CustProdYears выше.
WITH CustProdYears
AS(
SELECT DISTINCT
d.[Year] as SaleYear, s.FK_Product, s.FK_Customer
FROM @FACT_SALES s
JOIN @DIM_DATES d on s.FK_Date = d.BusinessKey
)
, CustomerSales
AS (
SELECT cpy.FK_Customer, cpy.FK_Product, d.YearMonthText, s.Sales
FROM CustProdYears cpy
JOIN @DIM_DATES d on cpy.[SaleYear] = d.[Year]
LEFT JOIN @FACT_SALES s
on s.FK_Customer = cpy.FK_Customer
and s.FK_Product = cpy.FK_Product
and s.FK_Date = d.BusinessKey
)
SELECT
Customer, Product, YearMonthText
, Sales = ISNULL(Sales, 0)
FROM @DIM_CUSTOMERS c
LEFT JOIN CustomerSales s ON c.BusinessKey = s.FK_Customer
LEFT JOIN @DIM_PRODUCTS p on s.FK_Product = p.BusinessKey
ORDER BY Customer, Product, YearMonthText
Последний ВЫБОР просто начинается с клиентов (поэтому все они появляются в результатах), а затем слева присоединяется к нашему CustomerSales CTE, чтобы показать все связанные продукты/годы (и продажи, если они есть).
Большое спасибо за ваш ответ. Это действительно правильный результат, и с точки зрения производительности определенно лучше сделать это непосредственно в представлении SQL, чем создавать показатели в Power BI.
Предположим, у меня есть дополнительная таблица FACT_BUDGET с теми же столбцами DIM, но со столбцом Budget, и в конце я хочу объединить оба столбца Sales и «Бюджет» на основе тех же столбцов DIM. Это хороший способ повторить этот запрос, как в вашем ответе на FACT_BUDGET, и в конце выполнить соединение между двумя таблицами, или можно ли продолжить работу над этим оператором SELECT и просто соединить его с помощью FACT_BUDGET. Я спрашиваю об этом, потому что иногда у клиента может быть budget, но не быть sales, или и то и другое, или и то, и другое NULL.
Я не уверен, что точно понимаю ваш сценарий, но вы можете создать представление, состоящее из двух таблиц. Возможно, вы захотите добавить справочный столбец, чтобы знать, откуда взялась каждая сумма. Что-то вроде UNION. Затем вы можете заменить таблицу продаж на новое представление CREATE VIEW SalesBudget AS SELECT 'Sales' as dataSource, ID, Product, Customer, Date, Sales FROM FACT_SALES UNION ALL SELECT 'Budget' as dataSource, ID, Product, Customer, Date, Sales FROM FACT_BUDGET.
Пожалуйста, поделитесь своей попыткой.