Chapter 4 of 12

Calculated Fields in Tableau

Master Tableau's calculation engine — from basic row-level formulas to aggregate expressions, table calculations, string and date functions, and logical operators — with real-world business examples.

Meritshot22 min read
TableauCalculated FieldsFormulasTableau Functions
All Tableau Chapters

Calculated Fields in Tableau

Data rarely arrives in exactly the shape you need for analysis. Calculated Fields are Tableau's answer — a built-in formula language that lets you create new fields derived from existing ones, without modifying the source data. From simple string concatenations to year-over-year comparisons and running totals, calculated fields are what transform Tableau from a charting tool into a serious analytical platform.


What Are Calculated Fields? Why Use Them?

A Calculated Field is a new virtual column that exists only within Tableau's data model. It is computed dynamically based on a formula you write, using the values of other fields. The original data source is never modified.

Why Calculated Fields Are Essential

Consider these common analytical needs that source data cannot satisfy directly:

Business NeedSource DataCalculated Field Solution
Profit margin percentageSales and Profit columns existSUM([Profit]) / SUM([Sales])
Customer age at purchaseBirth Date and Order Date columnsDATEDIFF('year', [Birth Date], [Order Date])
Flag high-value ordersOrder Amount columnIF [Order Amount] > 1000 THEN "High" ELSE "Standard" END
Extract domain from emailEmail columnSPLIT([Email], '@', 2)
Year-over-year growthSales column with datesTable calculation using LOOKUP()
Days since last purchaseLast Purchase Date columnDATEDIFF('day', [Last Purchase Date], TODAY())

Calculated Fields make your workbook self-contained: stakeholders interacting with your dashboard do not need access to auxiliary spreadsheets or pre-processed data — the calculations happen live inside Tableau.


Types of Calculations

Tableau has four types of calculations, each operating at a different level of the data pipeline.

1. Basic (Row-Level) Calculations

Row-level calculations are evaluated once per row in the underlying data, before any aggregation occurs. The result is a new column where each row gets its own computed value.

Example: [Profit] / [Sales] — computes a profit ratio for each individual order row.

Characteristics:

  • Computed before aggregation
  • Results can be aggregated (SUM, AVG, etc.) in the view
  • Appear in the Data pane as new fields
  • Can reference other row-level fields directly

2. Aggregate Calculations

Aggregate calculations use aggregation functions (SUM, AVG, COUNT, etc.) and operate on groups of rows defined by the dimensions in the view.

Example: SUM([Profit]) / SUM([Sales]) — computes profit margin at the aggregation level of whatever dimensions are in the view (e.g., per category, per region).

Key rule: You cannot mix aggregated and non-aggregated values in the same formula. SUM([Profit]) / [Sales] is invalid — Tableau will show an error.

3. Table Calculations

Table calculations are computed after the data has been aggregated and displayed in the view. They work on the visible data in the Tableau view — not the underlying source — making them sensitive to the view's structure.

Examples: Percent of total, running sum, moving average, rank, year-over-year difference.

Characteristics:

  • Computed last (after aggregation)
  • Depend on what is currently visible in the view (partition and direction)
  • Show as green pills with a delta symbol (∆) in the Data pane

4. Level of Detail (LOD) Expressions

LOD expressions allow you to control the granularity of an aggregation independently of the dimensions in the current view. They are the most powerful calculation type in Tableau.

Example: {FIXED [Customer ID] : MIN([Order Date])} — computes each customer's first order date regardless of what dimensions are in the view.

LOD expressions deserve their own chapter and will be covered in depth later in this course. This chapter introduces the concept and focuses on the first three types.


Creating a Calculated Field

There are three ways to create a Calculated Field in Tableau:

Method 1: From the Data pane

  1. In the Data pane, click the dropdown arrow (▾) at the top right
  2. Select Create Calculated Field

Method 2: From the Analysis menu

  1. Click Analysis in the menu bar
  2. Select Create Calculated Field

Method 3: Inline from a shelf

  1. Double-click an empty area on a shelf (Rows, Columns, Marks card)
  2. Tableau opens an inline calculation editor
  3. Type your formula and press Enter — an ad-hoc calculated field is created on that shelf

The Calculation Editor dialog opens for Methods 1 and 2.


The Calculation Editor

The Calculation Editor is Tableau's formula writing environment. It has several important features:

Interface Elements

  • Name field (top): Give your calculated field a meaningful name — Profit Margin, not Calc1
  • Formula area: Where you write your formula. Supports multi-line formulas.
  • Function reference (right panel): Browse all available functions by category — click any function to insert it with documentation
  • Status bar (bottom): Shows whether the formula is valid (green checkmark) or has an error (red X with description)
  • Auto-complete: As you type, Tableau suggests field names, functions, and parameters

Writing Formulas

Field references: Wrap field names in square brackets: [Sales], [Order Date], [Customer Name]

String literals: Use single quotes: 'North', 'High Value'

Numeric literals: Type directly: 0.1, 1000, 365

Comments: Use // for inline comments:

// This calculates the margin before taxes
SUM([Profit]) / SUM([Sales])

Error Handling

When a formula has an error, the status bar shows a red message. Common errors:

  • "Cannot mix aggregate and non-aggregate arguments": You combined SUM([Field]) with [Field] — use one or the other consistently
  • "Unknown function": Typo in function name — use auto-complete to avoid this
  • "Missing closing bracket": Unmatched [ or (
  • "Unexpected token": Syntax error — often a missing THEN, ELSE, or END

String Functions

String functions let you parse, format, transform, and combine text fields. They are row-level functions — computed per row.

Searching Within Strings

CONTAINS(string, substring) Returns TRUE if the substring is found anywhere within the string.

CONTAINS([Product Name], 'Chair')
// Returns TRUE for "Office Chair Pro", FALSE for "Desk Lamp"

STARTSWITH(string, substring) Returns TRUE if the string starts with the specified substring.

STARTSWITH([Email], 'admin')
// Returns TRUE for "admin@company.com"

ENDSWITH(string, substring) Returns TRUE if the string ends with the specified substring.

ENDSWITH([Email], '.gov')
// Returns TRUE for all government email addresses

FIND(string, substring, [start]) Returns the position (1-based) of the first occurrence of substring, or 0 if not found.

FIND([Product Name], 'Pro')
// Returns 8 for "Office Pro Chair", 0 for "Basic Desk"

Extracting Parts of Strings

LEN(string) Returns the number of characters in the string.

LEN([Customer Name])
// Returns 10 for "John Smith"

LEFT(string, n) Returns the leftmost n characters.

LEFT([Order ID], 2)
// Returns "CA" from "CA-2024-100234"

RIGHT(string, n) Returns the rightmost n characters.

RIGHT([ZIP Code], 4)
// Returns "1234" from "901234"

MID(string, start, [length]) Returns a substring starting at the specified position.

MID([Order ID], 4, 4)
// Returns "2024" from "CA-2024-100234" (starts at position 4, takes 4 chars)

SPLIT(string, delimiter, token_number) Splits a string by a delimiter and returns the specified piece (1-based).

SPLIT([Email], '@', 1)
// Returns "john.smith" from "john.smith@company.com"

SPLIT([Email], '@', 2)
// Returns "company.com"

Transforming Strings

UPPER(string) / LOWER(string) Converts to all uppercase or all lowercase.

UPPER([Customer Name])
// "john smith" → "JOHN SMITH"

LOWER([Email])
// "Admin@COMPANY.COM" → "admin@company.com"

TRIM(string) / LTRIM(string) / RTRIM(string) Removes leading and trailing whitespace (TRIM), left only (LTRIM), or right only (RTRIM).

TRIM([Product Name])
// "  Office Chair  " → "Office Chair"

REPLACE(string, old, new) Replaces all occurrences of a substring with a new value.

REPLACE([Phone], '-', '')
// "555-867-5309" → "5558675309"

Converting Between Types

STR(expression) Converts a number or date to a string.

"Order #" + STR([Order ID])
// Returns "Order #1234"

INT(expression) Converts a string or decimal number to an integer.

INT("42")   // Returns 42
INT(42.9)   // Returns 42 (truncates, does not round)

FLOAT(expression) Converts a string to a decimal number.

FLOAT("3.14")  // Returns 3.14

Number Functions

Number functions perform mathematical operations on numeric fields.

Rounding Functions

ROUND(number, decimals) Rounds to the specified number of decimal places.

ROUND([Sales], 2)      // 1234.5678 → 1234.57
ROUND([Sales], 0)      // 1234.5678 → 1235.0
ROUND([Sales], -2)     // 1234.5678 → 1200.0 (rounds to nearest hundred)

CEILING(number) Rounds up to the nearest integer.

CEILING(4.1)   // Returns 5
CEILING(-4.9)  // Returns -4

FLOOR(number) Rounds down to the nearest integer.

FLOOR(4.9)    // Returns 4
FLOOR(-4.1)   // Returns -5

Mathematical Functions

ABS(number) Returns the absolute value (distance from zero).

ABS(-150)   // Returns 150
ABS([Profit])  // Useful when you need magnitude regardless of sign

SQRT(number) Returns the square root.

SQRT(144)   // Returns 12.0

POWER(number, exponent) Raises a number to a power.

POWER(2, 10)   // Returns 1024
POWER([Sales], 2)   // Squares each sales value

DIV(integer1, integer2) Integer division (returns quotient without remainder).

DIV(17, 5)   // Returns 3

MOD(number, divisor) Returns the remainder after division.

MOD(17, 5)   // Returns 2
MOD([Row Number], 2)  // Returns 0 for even rows, 1 for odd — useful for alternating row color

Null Handling

ZN(expression) Returns the expression result if it is not null; returns 0 if it is null. Critical for preventing null propagation in calculations.

ZN([Profit])
// Returns actual profit where it exists, 0 for nulls
// Without ZN, NULL in a SUM propagates: SUM(5 + NULL) = NULL
// With ZN: SUM(ZN(5) + ZN(NULL)) = SUM(5 + 0) = 5

ISNULL(expression) Returns TRUE if the expression is null, FALSE otherwise.

ISNULL([Return Date])
// Returns TRUE for non-returned orders, FALSE for returned ones

Date Functions

Date functions are among the most commonly used in business analytics — for calculating ages, durations, fiscal periods, and time-based comparisons.

Extracting Date Parts

DATEPART(date_part, date) Returns a numeric value for the specified part of a date.

DATEPART('year', [Order Date])      // Returns 2024
DATEPART('month', [Order Date])     // Returns 1 through 12
DATEPART('quarter', [Order Date])   // Returns 1, 2, 3, or 4
DATEPART('weekday', [Order Date])   // Returns 1 (Sunday) through 7 (Saturday)
DATEPART('week', [Order Date])      // Week number 1-52
DATEPART('day', [Order Date])       // Day of month 1-31
DATEPART('hour', [Order DateTime])  // Hour 0-23

DATENAME(date_part, date) Returns a string name for the specified part (vs. a number from DATEPART).

DATENAME('month', [Order Date])     // Returns "January", "February", etc.
DATENAME('weekday', [Order Date])   // Returns "Monday", "Tuesday", etc.
DATENAME('quarter', [Order Date])   // Returns "Q1", "Q2", "Q3", "Q4"

DATETRUNC(date_part, date) Truncates a date to the beginning of the specified period — excellent for grouping.

DATETRUNC('month', #2024-05-17#)   // Returns 2024-05-01 (first of the month)
DATETRUNC('quarter', #2024-05-17#) // Returns 2024-04-01 (first of Q2)
DATETRUNC('year', #2024-05-17#)    // Returns 2024-01-01 (first of the year)

Calculating Date Differences

DATEDIFF(date_part, start_date, end_date) Returns the difference between two dates in the specified unit.

DATEDIFF('day', [Order Date], [Ship Date])
// Days from order to shipment — shipping lead time

DATEDIFF('month', [First Purchase Date], TODAY())
// Months since customer's first purchase — customer tenure

DATEDIFF('year', [Birth Date], TODAY())
// Approximate age in years

DATEDIFF('hour', [Incident Start], [Incident End])
// Duration of IT incidents in hours

Adding to Dates

DATEADD(date_part, increment, date) Adds or subtracts a specified number of date units.

DATEADD('day', 30, [Order Date])
// Date 30 days after order — payment due date

DATEADD('month', -1, TODAY())
// One month ago from today — useful for "last 30 days" filters

DATEADD('year', -1, [Order Date])
// Same date last year — for YoY comparisons

Date Constants and Dynamic Dates

TODAY() Returns today's date (without time component).

DATEDIFF('day', [Order Date], TODAY())
// Days since each order was placed

NOW() Returns the current date and time.

DATEDIFF('hour', [Last Login], NOW())
// Hours since user last logged in

Practical Date Calculations

Customer Age at Time of Purchase:

DATEDIFF('year', [Customer Birth Date], [Order Date])

Days Since Last Purchase (for churn analysis):

DATEDIFF('day', [Last Purchase Date], TODAY())

Fiscal Quarter (if fiscal year starts in April):

IF DATEPART('month', [Order Date]) >= 4
THEN "FY Q" + STR(INT((DATEPART('month', [Order Date]) - 4) / 3) + 1)
ELSE "FY Q" + STR(INT((DATEPART('month', [Order Date]) + 8) / 3) + 1)
END

Weekend vs Weekday Flag:

IF DATEPART('weekday', [Order Date]) IN (1, 7)
THEN "Weekend"
ELSE "Weekday"
END

Logical Functions

Logical functions control conditional behavior — performing different computations depending on whether conditions are met.

IF / ELSEIF / ELSE / END

The most fundamental conditional structure. Evaluates conditions in order and returns the first matching value.

IF [Profit] > 0 THEN "Profitable"
ELSEIF [Profit] = 0 THEN "Break Even"
ELSE "Loss"
END
IF [Sales] >= 10000 THEN "Platinum"
ELSEIF [Sales] >= 5000 THEN "Gold"
ELSEIF [Sales] >= 1000 THEN "Silver"
ELSE "Bronze"
END

Rule: Every IF must end with END. Every condition requires THEN. The ELSE branch is optional but recommended to handle unexpected values.


IIF (Inline IF)

A compact one-line conditional for simple true/false cases. Returns unknown if the condition itself is null.

Syntax: IIF(condition, true_result, false_result, [unknown_result])

IIF([Profit] > 0, "Profitable", "Not Profitable")

IIF(ISNULL([Return Date]), "Not Returned", "Returned")

IIF([Sales] > AVG([Sales]), "Above Average", "Below Average")

IIF is cleaner than IF for binary outcomes. Use IF/ELSEIF for three or more branches.


CASE / WHEN / THEN / ELSE / END

CASE evaluates a single expression against multiple possible values. More readable than a long IF/ELSEIF chain when checking one field for multiple specific values.

CASE [Region]
  WHEN "East" THEN "Eastern Division"
  WHEN "West" THEN "Western Division"
  WHEN "North" THEN "Northern Division"
  WHEN "South" THEN "Southern Division"
  ELSE "Other"
END
CASE DATEPART('month', [Order Date])
  WHEN 1 THEN "January"
  WHEN 2 THEN "February"
  WHEN 3 THEN "March"
  WHEN 4 THEN "April"
  WHEN 5 THEN "May"
  WHEN 6 THEN "June"
  WHEN 7 THEN "July"
  WHEN 8 THEN "August"
  WHEN 9 THEN "September"
  WHEN 10 THEN "October"
  WHEN 11 THEN "November"
  WHEN 12 THEN "December"
END

Boolean Operators

AND: Both conditions must be true

[Region] = "West" AND [Category] = "Technology"

OR: At least one condition must be true

[Segment] = "Consumer" OR [Segment] = "Home Office"

NOT: Negates a condition

NOT ISNULL([Return Date])
// TRUE for returned orders (Return Date is not null)

IN: Tests whether a value is in a list

[Region] IN ("East", "West")
// Equivalent to: [Region] = "East" OR [Region] = "West"

[Ship Mode] NOT IN ("Standard Class", "Second Class")
// Excludes standard and second class

Null Handling in Logic

ISNULL(expression)

ISNULL([Discount])
// Returns TRUE if discount is null (no discount applied)

IFNULL(expression, replacement) Returns the expression if not null; otherwise returns the replacement value. Similar to ZN() but works with any data type.

IFNULL([Discount], 0)
// Replaces null discounts with 0

IFNULL([Manager Name], "No Manager Assigned")
// String replacement for nulls

ZN(expression) Shorthand for IFNULL(expression, 0) — works only for numeric fields.

ZN([Profit])
// Same as IFNULL([Profit], 0)

Aggregate Calculations in Depth

Aggregate calculations use aggregation functions and are computed at the view's level of detail.

Core Aggregate Functions

FunctionDescriptionExample
SUM([field])Sum of all valuesSUM([Sales]) — total revenue
AVG([field])Arithmetic meanAVG([Order Value]) — average transaction
COUNT([field])Count of non-null rowsCOUNT([Order ID]) — number of orders
COUNTD([field])Count of distinct valuesCOUNTD([Customer ID]) — unique customers
MIN([field])Minimum valueMIN([Order Date]) — earliest order
MAX([field])Maximum valueMAX([Sales]) — largest single order
MEDIAN([field])Median valueMEDIAN([Salary]) — robust central tendency
STDEV([field])Sample standard deviationSTDEV([Test Score]) — score spread
VAR([field])Sample varianceStatistical analysis
ATTR([field])Single value if all rows agree, else *Confirm consistency within group

Profit Margin Formula

The classic example of why aggregate calculations matter. The wrong approach:

// WRONG — averages individual margins, which is mathematically incorrect
AVG([Profit] / [Sales])

The correct approach:

// CORRECT — divides total profit by total sales
SUM([Profit]) / SUM([Sales])

Why does this matter? Imagine two orders: $100 sale with $80 profit (80% margin) and $1000 sale with $100 profit (10% margin). The average of margins is (80% + 10%) / 2 = 45%, which is misleading. The actual blended margin is $180 / $1100 = 16.4%.

Name this calculated field Profit Margin and format it as a percentage.


Year-Over-Year Growth

A foundational business metric. This requires a table calculation:

  1. Create a simple line chart with [Order Date] (Year, discrete) on Columns and SUM([Sales]) on Rows
  2. Right-click the SUM([Sales]) pill on the Rows shelf
  3. Select Quick Table Calculation > Year Over Year Growth
  4. Tableau applies a LOOKUP table calculation that compares each year to the previous

Or write it manually as a calculated field using a table calculation:

(SUM([Sales]) - LOOKUP(SUM([Sales]), -1)) / ABS(LOOKUP(SUM([Sales]), -1))

This formula: takes current year sales, subtracts the previous year's sales (LOOKUP -1 means "look back 1 period"), and divides by the absolute value of last year to get a percentage change.

Format this field as a percentage. Values above 0% represent growth; below 0% represent decline.


Running Totals and Moving Averages

These are classic table calculations — computed on the aggregated, visible data in the view.

Running Total

A running total accumulates values from the first data point to the current one.

Quick method:

  1. Place SUM([Sales]) on the Rows shelf with [Order Date] (Month) on Columns
  2. Right-click the SUM([Sales]) pill → Quick Table Calculation > Running Total

Manual formula (for use in custom calculations):

RUNNING_SUM(SUM([Sales]))

Use cases: cumulative revenue toward an annual target, running total of customers acquired.

Moving Average

A moving average smooths out short-term fluctuations by averaging the last N periods.

Quick method: Right-click the SUM([Sales]) pill → Quick Table Calculation > Moving Average

Manual formula for a 3-month moving average:

WINDOW_AVG(SUM([Sales]), -2, 0)
// Averages the current month and the 2 previous months

Manual formula for a 12-month moving average:

WINDOW_AVG(SUM([Sales]), -11, 0)

Use cases: smoothed sales trend, rolling 7-day average of daily metrics.


Bins: Creating Histograms

Bins group a continuous measure into discrete ranges, enabling histogram analysis.

Creating Bins Automatically

  1. Right-click any measure in the Data pane (e.g., [Sales])
  2. Select Create > Bins
  3. Set the bin size (e.g., 500 — groups orders into $0-$499, $500-$999, etc.)
  4. Click OK — Tableau creates a [Sales (bin)] field
  5. Drag [Sales (bin)] to Columns and COUNT([Orders]) (or CNT([Sales])) to Rows
  6. Result: a histogram showing order frequency by dollar range

Choosing the Right Bin Size

Too few bins (size too large) hides the distribution shape. Too many bins (size too small) creates noise. A starting heuristic: use SQRT(number of rows) as the number of bins, then adjust.

For 10,000 rows: start with approximately 100 bins. Adjust iteratively until the shape is clear.


Sets in Calculated Fields

Sets are custom segments created by defining which dimension members are "In" and which are "Out." They can be used within calculated fields.

Using a Set in a Calculation

Once you have created a set (right-click a dimension → Create > Set), you can reference it in a calculated field:

IF [Top Customers] THEN "Key Account"
ELSE "Standard Account"
END

Sets evaluate to TRUE (In) or FALSE (Out), so they can be used directly in IF conditions.

Dynamic vs Fixed Sets

  • Fixed sets: Static list of members you manually select
  • Computed sets (Top N sets): Dynamically include the top or bottom N members by a measure — updates automatically as data changes

Practice Exercises

Exercise 1: String Manipulation

Objective: Clean and enrich text data using string functions.

Dataset: Superstore (or any dataset with customer names and order IDs)

Tasks:

  1. The [Order ID] field in Superstore has the format CA-2024-152156. Create a calculated field called Order Year that extracts the year portion (the middle 4 characters).

    • Hint: Use SPLIT([Order ID], '-', 2) or MID([Order ID], 4, 4)
  2. Create a calculated field called Customer First Name that extracts only the first name from [Customer Name] (assuming "First Last" format).

    • Hint: Use LEFT([Customer Name], FIND([Customer Name], ' ') - 1)
  3. Create a calculated field called Standardized Region that converts region names to uppercase.

    • Hint: UPPER([Region])
  4. Build a bar chart using Order Year as the dimension and COUNT([Order ID]) as the measure to see order volume by year.

Deliverable: The three calculated field formulas and a screenshot of the yearly order count bar chart.


Exercise 2: Date Intelligence

Objective: Build time-based calculated fields for business analysis.

Dataset: Superstore

Tasks:

  1. Create a calculated field called Shipping Lead Time (Days) that counts the number of days between order date and ship date.

    • Formula: DATEDIFF('day', [Order Date], [Ship Date])
  2. Create a calculated field called Is Late Shipment that flags any order with a shipping lead time greater than 5 days.

    • Formula: IF DATEDIFF('day', [Order Date], [Ship Date]) > 5 THEN "Late" ELSE "On Time" END
  3. Create a calculated field called Order Quarter that returns a readable label like "Q1 2024".

    • Formula: "Q" + STR(DATEPART('quarter', [Order Date])) + " " + STR(DATEPART('year', [Order Date]))
  4. Build a view: [Ship Mode] on Rows, AVG([Shipping Lead Time (Days)]) on Columns, and [Is Late Shipment] on Color. What does this reveal about the relationship between shipping mode and on-time performance?

Deliverable: The three calculated field formulas, the completed bar chart, and a 3-4 sentence interpretation of what the chart reveals.


Exercise 3: Conditional Logic and Segmentation

Objective: Use IF/CASE logic to create meaningful business segments.

Dataset: Superstore

Tasks:

  1. Create a Customer Tier calculated field that segments customers by their total sales:

    • Platinum: SUM([Sales]) >= 5000
    • Gold: SUM([Sales]) >= 2000
    • Silver: SUM([Sales]) >= 500
    • Bronze: all others
    • Note: This is an aggregate calculation (uses SUM) — it must be used as a dimension in the view, not a row-level segment.
  2. Create a Discount Category calculated field (row-level) that labels each order:

    • "No Discount" if [Discount] = 0
    • "Low Discount" if [Discount] <= 0.20
    • "Medium Discount" if [Discount] <= 0.40
    • "High Discount" otherwise
  3. Create a Profit Flag calculated field:

    • "Profitable" if [Profit] > 0
    • "Break Even" if [Profit] = 0
    • "Loss" if [Profit] < 0
  4. Build a stacked bar chart: [Sub-Category] on Rows, COUNT([Order ID]) on Columns, [Discount Category] on Color.

Deliverable: The three calculated field formulas, the stacked bar chart, and a brief observation about which sub-categories have the highest proportion of high-discount orders.


Exercise 4: Advanced Aggregations and Table Calculations

Objective: Build a multi-metric analysis using aggregate and table calculations.

Dataset: Superstore

Tasks:

  1. Create a Profit Margin calculated field using the correct aggregate formula:

    • SUM([Profit]) / SUM([Sales])
    • Format as a percentage with 1 decimal place
  2. Create a line chart showing monthly SUM([Sales]) over time. Apply a Running Total table calculation to it. Add a second axis showing the monthly sales (not running total) as a bar. Synchronize the axes.

    • This dual-axis combination shows both individual month performance and cumulative progress.
  3. Apply a Year Over Year Growth quick table calculation to a bar chart of SUM([Sales]) by year. Format as percentages. Which year had the highest growth rate?

  4. Create a histogram of [Sales] with a bin size of $250. Describe the shape of the distribution:

    • Is it symmetric or skewed?
    • Where is the peak (most common order size range)?
    • Are there outlier orders significantly larger than most?

Deliverable: The Profit Margin formula, screenshots of the running total dual-axis chart and the YoY growth bar chart, and a written description of the sales distribution from the histogram.


Summary

This chapter covered the full range of Tableau's calculation capabilities — from the simplest string manipulation to multi-layered aggregate expressions.

Key takeaways:

  • Calculated Fields create virtual columns derived from existing data — non-destructive, dynamic, and stored in the workbook rather than the source
  • Tableau has four calculation types: Row-level (per row, before aggregation), Aggregate (per group, at view granularity), Table (post-aggregation, view-sensitive), and LOD (independent of view granularity)
  • The Calculation Editor provides auto-complete, syntax highlighting, inline documentation, and real-time error checking
  • String functions — CONTAINS, SPLIT, LEFT/RIGHT/MID, UPPER/LOWER, REPLACE, TRIM — enable text parsing and standardization
  • Number functions — ROUND, CEILING, FLOOR, ABS, POWER, ZN — handle mathematical transformations and null safety
  • Date functions — DATEPART, DATENAME, DATETRUNC, DATEDIFF, DATEADD, TODAY() — are essential for all time-based analysis
  • Logical functions — IF/ELSEIF/ELSE, IIF, CASE/WHEN, AND/OR/NOT, IN, ISNULL/IFNULL/ZN — enable conditional segmentation and business rule encoding
  • The correct profit margin formula is SUM([Profit]) / SUM([Sales]) — not AVG([Profit] / [Sales])
  • Running totals and moving averages use table calculations that operate on the visible aggregated data
  • Bins convert continuous measures into discrete ranges for histogram analysis
  • Sets can be referenced in calculated fields as boolean conditions for custom segmentation

In the next chapter, you will master Tableau's most powerful calculation type — Level of Detail (LOD) expressions — which let you compute aggregations at any granularity, independent of what is currently in the view.