From Raw Pharma Data to Star Schema: SQL Server + Power BI Explained!

Case Study: Building a Pharma Sales Star Schema with SQL Server and Power BI

Sep 30, 2026 · @kale

Case study overview: from flat pharma file to analytics-ready model

This project turns a single, flat pharma sales file into a star schema in SQL Server, then loads it into Power BI for fast, reliable sales analytics.

The business problem. Pharma sales data usually arrives as one wide table, with customers, products, sales reps and dates repeated on every row. Reports built straight on that table are slow to maintain, easy to get wrong, and hard to extend when a new question arrives, such as sales by product class or by sales team.

The solution. Separate descriptive attributes from measurable events. A central fact table stores sales quantities and amounts, and surrounding dimension tables describe who, what, where and when. Power BI then relates the tables and calculates measures once, for every report to reuse.

Who it is for. BI developers, data analysts and finance or commercial teams in pharmaceutical distribution, plus Power BI learners who want a realistic data modelling project.

The raw data and its problems

The source is one denormalized table of pharma sales transactions. A typical layout carries columns such as distributor, customer name, city, country, sales channel, product name, product class, quantity, price, sales amount, month, year, sales rep, manager and sales team. [Adjust this list to match the columns in your source file.]

Why a flat table falls short

  • Repeated text. Customer, city and product names repeat on thousands of rows, which wastes storage and invites spelling inconsistencies.
  • Mixed levels of detail. Customer, product and rep attributes sit beside transaction amounts, so it is unclear what one row represents.
  • Weak time analysis. Month and year stored as text or separate columns make year-to-date and prior-year comparisons awkward.
  • Fragile reports. Every new filter or grouping means reworking the same wide table instead of reusing a clean model.

Star schema design

The design starts with the grain: one row in the fact table equals one sales line for one customer, product, sales rep and month. Every other decision follows from that sentence.

TableTypeKeyTypical columns
FactSalesFactSurrogate keys to each dimensionQuantity, Price, SalesAmount
DimCustomerDimensionCustomerKeyCustomer name, city, country, channel, sub-channel
DimProductDimensionProductKeyProduct name, product class
DimSalesRepDimensionSalesRepKeyRep name, manager, sales team
DimDistributorDimensionDistributorKeyDistributor name
DimDateDimensionDateKeyDate, month, quarter, year

Design rules applied

  • Each dimension has an integer surrogate key, so the model does not depend on text names.
  • Fact tables hold keys and numeric measures only.
  • Dimensions connect to the fact table with one-to-many relationships, so filters flow from dimension to fact.
  • A dedicated date table supports time intelligence in DAX.

The resulting shape looks like a star, with FactSales at the centre and one dimension on each point. [Insert your star schema diagram from the video here.]

Building the schema in SQL Server

The raw file is first loaded into a staging table. Dimensions are then built from its distinct values, and the fact table is loaded by joining staging back to those dimensions. Column names below are examples.

1. Create a dimension from distinct staging values

CREATE TABLE dbo.DimProduct (
    ProductKey   INT IDENTITY(1,1) PRIMARY KEY,
    ProductName  NVARCHAR(200) NOT NULL,
    ProductClass NVARCHAR(100) NULL
);

INSERT INTO dbo.DimProduct (ProductName, ProductClass)
SELECT DISTINCT LTRIM(RTRIM(ProductName)), LTRIM(RTRIM(ProductClass))
FROM dbo.Stg_PharmaSales;

2. Create the fact table with foreign keys

CREATE TABLE dbo.FactSales (
    SalesKey     BIGINT IDENTITY(1,1) PRIMARY KEY,
    DateKey      INT NOT NULL,
    CustomerKey  INT NOT NULL REFERENCES dbo.DimCustomer(CustomerKey),
    ProductKey   INT NOT NULL REFERENCES dbo.DimProduct(ProductKey),
    SalesRepKey  INT NOT NULL REFERENCES dbo.DimSalesRep(SalesRepKey),
    Quantity     DECIMAL(18,2) NOT NULL,
    Price        DECIMAL(18,2) NULL,
    SalesAmount  DECIMAL(18,2) NOT NULL
);

3. Load the fact table by looking up each key

INSERT INTO dbo.FactSales (DateKey, CustomerKey, ProductKey, SalesRepKey, Quantity, Price, SalesAmount)
SELECT d.DateKey, c.CustomerKey, p.ProductKey, r.SalesRepKey,
       s.Quantity, s.Price, s.Sales
FROM dbo.Stg_PharmaSales AS s
JOIN dbo.DimCustomer AS c ON c.CustomerName = s.CustomerName AND c.City = s.City
JOIN dbo.DimProduct  AS p ON p.ProductName  = s.ProductName
JOIN dbo.DimSalesRep AS r ON r.RepName      = s.SalesRepName
JOIN dbo.DimDate     AS d ON d.[Year] = s.[Year] AND d.[MonthNumber] = s.[MonthNumber];

4. Validate before loading Power BI. Compare row counts and total sales between staging and the fact table, and check for unmatched keys. If the totals differ, a join is dropping or duplicating rows.

Loading into Power BI and writing measures

  1. Connect. Use Get Data, SQL Server, and import the fact and dimension tables. Import mode suits most pharma sales volumes and keeps reports fast.
  2. Check relationships. Confirm each dimension key relates to the matching fact key, one-to-many, with single-direction filtering.
  3. Mark the date table. Set DimDate as the date table so time intelligence works.
  4. Hide keys. Hide surrogate keys and the raw fact columns, and expose measures instead.
  5. Create measures. Build them once on the model, then reuse them in every visual.
Total Sales = SUM ( FactSales[SalesAmount] )

Total Quantity = SUM ( FactSales[Quantity] )

Sales PY =
CALCULATE ( [Total Sales], SAMEPERIODLASTYEAR ( DimDate[Date] ) )

Sales YoY % =
DIVIDE ( [Total Sales] - [Sales PY], [Sales PY] )

Sales YTD =
TOTALYTD ( [Total Sales], DimDate[Date] )

With the model in place, one slicer on product class or sales team filters every visual consistently, because all filtering flows through the dimensions.

Results, business value and lessons learned

What the star schema delivers

  • One trusted definition of sales, quantity and growth, reused across every report.
  • Faster refreshes and smaller models, since text attributes are stored once in dimensions.
  • Easy extension: a new dimension such as region or payer adds a table and a key, without rebuilding existing reports.
  • Clear answers to commercial questions: top products by class, sales by channel, rep and team performance, and year-over-year trends.

[Add 2 or 3 findings from your dashboard, for example the top product class by sales, the strongest sales team, and the year with the highest growth.]

Lessons learned

  • Define the grain first and write it as a sentence.
  • Clean and trim text in the staging layer, so dimensions do not hold near-duplicate values.
  • Reconcile totals between source, fact table and Power BI before building visuals.
  • Keep business logic in measures rather than calculated columns where possible.

Frequently asked questions

What is a star schema in Power BI? A star schema is a data model with one central fact table of measurable events, surrounded by dimension tables that describe them. It is the recommended structure for Power BI because it keeps models fast and easy to understand.

Why use SQL Server before Power BI? SQL Server lets you clean, validate and reshape data once in a governed database, so Power BI receives analytics-ready tables instead of a raw file.

What is the grain of a fact table? The grain defines what one row represents, such as one sales line per customer, product, rep and month.

What is the difference between a fact table and a dimension table? Fact tables store numbers you measure, like quantity and sales. Dimension tables store the descriptive attributes you filter and group by, like product, customer and date.

Do I need a date table? Yes. A dedicated, marked date table is required for reliable time intelligence functions such as year-to-date and prior-year comparisons.

Try it yourself

Watch the full tutorial, then download the complete source files and build the star schema yourself. Need a SQL Server and Power BI data model for your own sales data? Contact datascientist.ca.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top