✍️ Field Notes

Thoughts on Data & BI

Practical notes on Power BI, DAX and enterprise BI delivery — from projects across Singapore, Qatar, USA and India.

📰 Latest Articles

📊
Window Functions in SQL: The BI Developer's Cheat Sheet for Running Totals and Rankings

ROW_NUMBER, RANK, LAG, running totals, year-over-year — the window function patterns that replace almost every self-join in BI reporting SQL.

RLS vs OLS: Two Different Answers to "This User Shouldn't See That"
RLS vs OLS: Two Different Answers to "This User Shouldn't See That"

Row-Level Security and Object-Level Security get used interchangeably, but they restrict along different axes and fail in different ways. A practical walkthrough of dynamic RLS, OLS via Tabular Editor, the bidirectional relationship trap, and pushing security down into the Fabric Warehouse.

📊
The DAX Time Intelligence Mistake That Silently Breaks at Fiscal Year Boundaries

Your Year-over-Year measure works perfectly all year — until the fiscal year rolls over, and the comparison quietly starts pulling the wrong period. Here's why calendar-based time intelligence functions and fiscal calendars don't mix the way most people assume.

📊
Documenting a Power BI Data Model So the Next Developer Doesn't Hate You

The model isn't self-explanatory — it's self-explanatory to the one person who built it, for exactly as long as they remember why.

📊
Loading NetSuite Data into a Microsoft Fabric Lakehouse with SuiteQL: A Field Guide

Authenticating to NetSuite, paging past the 1000-row API cap, and landing data cleanly in a Fabric Lakehouse — a practitioner's walkthrough of the defaults and gotchas that cost real time, and how to sidestep each one.

The Incremental Load Mistake That Silently Misses Updated Records
The Incremental Load Mistake That Silently Misses Updated Records

Full Load, Incremental Load, and CDC aren't just three options — each has a specific failure mode most pipelines hit eventually. Here's the incremental load filter mistake that quietly excludes legitimate updates, and why CDC exists to solve exactly this.

📊
Why Your SQL Query Is Slow: Reading an Execution Plan Without Panic

Stop guessing why your query is slow — read the execution plan in the right order and spot the patterns that actually kill BI performance.

📊
The Difference Between a Data Warehouse, a Data Lake, and a Lakehouse — Explained Without Buzzwords

Warehouse, lake, and lakehouse are three different answers to who can write, who can read, and what breaks if both happen at once.

📊
The DirectQuery Trap: When 'Real-Time' Reporting Actually Slows Everyone Down

Every visual in a DirectQuery report is a live round trip to the source - stack enough of them and real-time becomes the slowest thing on the page.

📊
Building a Forecast vs Actuals Report Without a Single Hardcoded Date

A hardcoded cutoff date works perfectly in every demo, then quietly breaks the report the first month nobody remembers to update it.

📊
Building a Centralized Actuals vs Forecast Revenue Measure in Power BI

A step-by-step guide to blending actuals and forecast data in Power BI using a single master DAX measure — handling mixed-period quarters, stacked bar charts, product breakdowns, and drillthrough row inflation using ISINSCOPE and SWITCH(TRUE()).

📊
Two Ways to Talk to a Microsoft Fabric Data Agent — and Which One Belongs in Your App

A published Fabric Data Agent gives you two programmatic surfaces: the new MCP server endpoint and the older Published URL / Python client SDK. They return the same grounded answers, so it's easy to pick the wrong one. Here's how they actually differ, why authentication — not transport — decides your architecture, and which path belongs behind a front-end app.