Streamlining your tech stack for maximum efficiency

Learn, explore, and grow with our knowledge hub.

SQL Order-to-Cash Bottleneck Analysis Tutorial | Smart Statistics
SQL + Power BI Practical Guide

Find Where Orders Get Stuck

A customer order can look perfectly healthy in a headline sales report while quietly sitting in a credit queue, waiting for stock, awaiting dispatch or remaining uninvoiced.

Traditional reporting often measures the final result. Bottleneck analysis measures the time between the events that created it.

In this tutorial, you will use SQL window functions to turn an order-event history into stage durations, SLA breaches, ageing flags and a Power BI action view showing where operational delays are holding up cash.

Stage Time See where elapsed time accumulates.
Ageing Orders Find transactions exceeding expectations.
Root Causes Group recurring operational blockers.
Cash Priority Focus on high-value delays first.
Order-to-Cash Bottleneck Monitor Illustrative operational dashboard
Monitoring active
Open Orders 1,284 Illustrative figure
Over SLA 143 Illustrative figure
Median Cycle 4.8d Illustrative figure
Cash at Risk £612k Illustrative figure

Median Stage Duration

Order Entry
0.5d
Credit Check
1.8d
Picking
1.0d
Dispatch
0.7d
Invoice
2.1d

Issues Requiring Action

Credit Hold 47 illustrative orders
Awaiting Stock 39 illustrative orders
Invoice Queue 31 illustrative orders
Management message

Invoice release is the longest illustrative median stage. Prioritise ageing, high-value orders before month-end.

All dashboard figures are illustrative examples.
The Hidden Delay Problem

“Order Took Seven Days” Does Not Tell You Why

Total cycle time is useful, but it does not identify which hand-off, queue or control caused the delay.

Long Waiting Time

Orders can spend more time waiting between teams than being actively processed.

Queue Build-Up

A team may appear productive while unfinished work accumulates immediately before or after it.

Poor Hand-Offs

The delay may sit between departments rather than inside a single department's own work.

Cash Is Delayed

If invoicing or fulfilment is late, operational delay can eventually become a working-capital problem.

The Event Model

Turn the Process into Dated Events

Instead of keeping only the current order status, retain the important milestones that show how the order moved through the process.

Order Created

Capture the commercial starting point.

Credit Released

Measure time waiting for financial approval.

Picked

Track the warehouse fulfilment milestone.

Dispatched

Measure the delay before goods leave the site.

Invoiced

Identify when the order becomes billable.

Practical SQL Build

Build the Bottleneck Monitor Step by Step

Create an Order Event Table

The most useful starting structure is one row per order event rather than one row per order.

OrderID | EventType       | EventTime
--------|-----------------|--------------------
10001   | Order Created   | 2026-08-03 09:14
10001   | Credit Released | 2026-08-03 12:46
10001   | Picked          | 2026-08-04 08:28
10001   | Dispatched      | 2026-08-04 14:51
10001   | Invoiced        | 2026-08-05 10:06

Add useful business attributes where available:

  • Customer
  • Region
  • Order value
  • Product group
  • Site or warehouse
  • Account manager

Use LEAD() to Find the Next Event

SQL window functions are useful because they let you compare rows inside the same order without losing the event-level detail.

WITH SequencedEvents AS (
    SELECT
        OrderID,
        EventType,
        EventTime,

        LEAD(EventType) OVER (
            PARTITION BY OrderID
            ORDER BY EventTime
        ) AS NextEventType,

        LEAD(EventTime) OVER (
            PARTITION BY OrderID
            ORDER BY EventTime
        ) AS NextEventTime

    FROM dbo.OrderEvents
)

SELECT *
FROM SequencedEvents;
PARTITION BY restarts the sequence for each order. ORDER BY determines the event chronology inside that order.

Calculate the Time Between Events

Once the next timestamp is available, calculate elapsed time for the stage.

WITH SequencedEvents AS (
    SELECT
        OrderID,
        EventType,
        EventTime,

        LEAD(EventType) OVER (
            PARTITION BY OrderID
            ORDER BY EventTime
        ) AS NextEventType,

        LEAD(EventTime) OVER (
            PARTITION BY OrderID
            ORDER BY EventTime
        ) AS NextEventTime

    FROM dbo.OrderEvents
)

SELECT
    OrderID,
    EventType,
    NextEventType,
    EventTime,
    NextEventTime,

    DATEDIFF(
        MINUTE,
        EventTime,
        NextEventTime
    ) AS StageMinutes

FROM SequencedEvents
WHERE NextEventTime IS NOT NULL;

Minutes provide flexibility. You can convert them to hours or days later according to the reporting need.

Decide whether your process should use calendar time or business-hours time. For some workflows, overnight and weekend periods should be treated differently.

Compare Each Stage with an SLA

Create a small rules table containing the expected duration of each stage.

StageName        | SlaMinutes
-----------------|-----------
Order Created    | 240
Credit Released  | 480
Picked           | 720
Dispatched       | 480

Join the event-duration result to the rule table:

SELECT
    e.OrderID,
    e.EventType,
    e.NextEventType,
    e.StageMinutes,
    s.SlaMinutes,

    CASE
        WHEN e.StageMinutes > s.SlaMinutes
            THEN 1
        ELSE 0
    END AS IsSlaBreach

FROM EventDurations e

LEFT JOIN dbo.StageSla s
    ON e.EventType = s.StageName;
Keeping the SLA in a table instead of hard-coding it makes the rules easier to review and maintain.

Add Order Value and Prioritise Material Delays

Two overdue orders are not necessarily equally important.

Add the commercial value of each order so the operations team can distinguish between:

  • Low-value routine exceptions
  • High-value orders approaching month-end
  • Strategic customer orders
  • Orders repeatedly breaching the same stage

An illustrative priority rule:

CASE
    WHEN IsSlaBreach = 1
         AND OrderValue >= 50000
        THEN 'Critical'

    WHEN IsSlaBreach = 1
         AND OrderValue >= 10000
        THEN 'High'

    WHEN IsSlaBreach = 1
        THEN 'Review'

    ELSE 'Normal'
END AS ActionPriority
The £50,000 and £10,000 thresholds above are illustrative examples only. Use business-approved thresholds in a real implementation.

Build an Action-Focused Power BI Page

Do not stop with a chart showing average lead time. Give the user enough context to act.

  • Open orders
  • Orders currently over SLA
  • Median stage duration
  • Order value currently delayed
  • Longest stage
  • Top bottleneck reason
  • High-priority ageing orders

Add a detailed action table containing:

  • Order number
  • Customer
  • Current stage
  • Time in stage
  • SLA
  • Order value
  • Reason code
  • Owner
The dashboard should answer: where is the delay, why is it happening, and which order should we act on first?
From Analytics to Action

A Bottleneck Dashboard Should Change What Happens Next

Process analytics becomes useful when the insight is linked to ownership and a practical operational response.

Resolve Credit Holds

Separate genuine credit risk from transactions simply waiting for review.

Prioritise Stock

Surface high-value orders that are ready to progress once missing stock is available.

Clear Invoice Queues

Identify completed fulfilment that is still waiting to become an invoice.

Fix Recurring Causes

Use trend analysis to distinguish isolated exceptions from structural process problems.

Frequently Asked Questions

Order-to-Cash Analytics FAQs

What is order-to-cash bottleneck analysis?
It measures how long transactions spend in individual process stages so teams can identify waiting time, ageing orders and recurring operational blockers rather than looking only at total cycle time.
Why are SQL window functions useful here?
Functions such as LEAD() and LAG() allow one event to be compared with another event inside the same order while preserving event-level detail.
Should I use LEAD() or LAG()?
Either can work depending on how you structure the analysis. LEAD() is convenient when calculating the time from the current event to the next event. LAG() is useful when comparing the current event with the preceding event.
Should stage time use calendar hours or working hours?
That depends on the operational process. A 24-hour distribution environment and an office-hours approval process may require different elapsed-time rules.
Can this approach be used outside order-to-cash?
Yes. The same event-sequencing pattern can support recruitment, purchasing, service requests, claims, production, approvals and many other multi-stage processes.
Can Power BI calculate the stage durations instead?
It can in some models, but preparing event sequencing and stage durations upstream in SQL can simplify the semantic model and make the transformation easier to reuse.
Does cash at risk mean the full order value will be lost?
No. In this tutorial, cash at risk is an illustrative prioritisation concept representing value currently delayed in the process. It should not automatically be interpreted as expected financial loss.
How can Smart Statistics help?
Smart Statistics helps UK businesses combine SQL, Power BI and process analytics to expose operational delays, improve visibility and turn reporting into clearer business action.

Stop Measuring Only How Many Orders You Have. Measure Where the Time Is Going.

Smart Statistics helps UK businesses turn operational event data into reporting that reveals waiting time, bottlenecks, exceptions and the transactions that deserve attention first.

Whether the process sits in sales, finance, operations, service delivery or supply chain, the objective is the same: make hidden delays visible before they become larger customer, cost or cash-flow problems.