Data Visualization

Data Visualization · Tableau · Data Analysis

Day 149: When Tableau Lied to Me (And How I Caught It)

October 10, 2025 – Today’s Vibe: Trust Issues with My Tools

October 10, 2025 – Today’s Vibe: Trust Issues with My Tools

You know that feeling when you present a beautiful dashboard to stakeholders, they nod approvingly, and then someone asks, “Wait, why does this number not match our finance report?” and your stomach drops? Yeah. That was my Thursday morning.

The Hardship: The Dashboard That Told Lies

I’d spent two days building a gorgeous Tableau dashboard showing monthly revenue trends by region. The charts were chef’s kiss, the color scheme was on-brand, and the interactivity was smooth. I was proud. I sent it to leadership. Then, 15 minutes before the big presentation call, our CFO emailed: “Your Q3 West Coast revenue is $2.3M, but Finance shows $1.8M. Which is correct?”

Cue the cold sweat. I opened both datasets. Finance was right. My dashboard was wrong. I had 30 minutes to figure out why before making a fool of myself in front of the executive team.

The Investigation: Aggregation Ambush

The issue wasn’t with my data source (thank goodness). It was with how Tableau was aggregating the data, and I’d made a rookie mistake: I hadn’t paid attention to the level of detail in my calculated field.

Here’s what I’d done wrong. My data had multiple rows per order (one row per line item), and I’d created a calculated field for revenue:

SUM([Amount])

Seems fine, right? WRONG. When I filtered by region and month, Tableau was summing at the line-item level, which meant if an order had 5 line items, I was counting the order total 5 times. My revenue numbers were inflated by a factor of however many line items existed per order.

I felt like an idiot. This is literally Data Viz 101: understand your data granularity.

The Lesson: Know Your Level of Detail (Or Suffer)

Here’s what I should’ve done from the start:

1. Use FIXED LOD Expressions for Unambiguous Aggregations

I rewrote my revenue calculation using a Level of Detail (LOD) expression to ensure I was summing at the order level, not the line-item level:

{ FIXED [Order ID] : SUM([Amount]) }

This calculates the total revenue per order first, then aggregates it by region/month, preventing double-counting. My numbers instantly matched Finance’s report.

2. Always Validate Against Source Data

Before building any viz, I now run this sanity check:

-- In my database
SELECT 
    DATE_TRUNC('month', order_date) as month,
    region,
    SUM(DISTINCT order_total) as revenue
FROM orders
WHERE order_date BETWEEN '2025-07-01' AND '2025-09-30'
  AND region = 'West Coast'
GROUP BY month, region;

Then I compare that result to my Tableau dashboard. If they don’t match within 1%, I investigate immediately.

3. Build a “Data Quality Check” Sheet

I now include a hidden worksheet in every Tableau workbook that shows:

  • Total row count in the data source
  • Total revenue (using FIXED LOD)
  • Total revenue (using naive SUM)
  • Difference between the two

If the difference isn’t zero, I know I have a granularity problem.

// Data Quality Check Calculated Field
SUM([Amount]) - SUM({ FIXED [Order ID] : SUM([Amount]) })

If this returns anything other than 0, red flags fly.

Mistakes I Vow Not to Repeat

  1. Assuming my aggregations are correct without testing. I got complacent because the dashboard looked good.
  2. Not cross-referencing with source data. Always validate against SQL queries or Excel reports before presenting.
  3. Ignoring the data structure. I should’ve mapped out the grain of my data (order vs. line item) before building.
  4. Not adding validation metrics. Every dashboard should have a “sanity check” sheet, even if stakeholders never see it.

Your Automation Toolkit: Tableau Validation Workflow

Here’s my new process to prevent future dashboard disasters:

1. Pre-Build Data Audit (Python + SQL)

Before touching Tableau, I run this Python script to understand my data:

import pandas as pd
from sqlalchemy import create_engine

engine = create_engine('postgresql://user:pass@host:5432/db')

# Check for duplicates and granularity
query = """
SELECT 
    COUNT(*) as total_rows,
    COUNT(DISTINCT order_id) as unique_orders,
    COUNT(*) / NULLIF(COUNT(DISTINCT order_id), 0) as rows_per_order
FROM orders;
"""

df = pd.read_sql(query, engine)
print(df)

# If rows_per_order > 1, you have a granularity issue

2. Embed Validation Directly in Tableau

I now add a “Validation” dashboard tab (hidden from users) that shows:

  • Expected Revenue (from SQL): Hardcode the finance number as a parameter
  • Calculated Revenue (from Tableau): My dashboard’s number
  • Variance: The difference
  • Variance %: Should be < 1%
// Create a parameter: [Finance_Revenue] = 1800000
// Create calculated field: [Variance %]
(SUM({ FIXED [Order ID] : SUM([Amount]) }) - [Finance_Revenue]) / [Finance_Revenue]

If variance is >1%, I don’t publish.

3. Automate Cross-Checks with Tableau Prep

I now use Tableau Prep to clean and aggregate data before it hits Tableau Desktop:

  • Deduplicate orders
  • Pre-calculate order totals
  • Export a clean “order-level” dataset

This way, my visualizations only work with already-aggregated data, eliminating granularity risks.

4. Schedule Automated Alerts

Using Tableau Server’s alerting feature, I set up a weekly email that triggers if my dashboard’s revenue deviates >5% from a baseline metric stored in our data warehouse.

The Takeaway

Today’s lesson: Tableau didn’t lie to me. I lied to Tableau by not understanding my data. Visualization tools are incredibly powerful, but they’re also incredibly good at confidently presenting wrong information if you feed them ambiguous instructions.

The real skill isn’t making pretty charts. It’s knowing your data well enough to catch when those charts are wrong before your CFO does.

What’s your worst dashboard disaster story? Drop it in the comments! I promise you’re among friends here, and I need to know I’m not the only one who’s sweated through a stakeholder meeting.


Tomorrow: “API Integration From Hell: How I Spent 6 Hours Debugging a Typo.” (Yes, really.)