Home › Blog › Slow-moving items in SAP Business One

SAP Business One slow-moving items report

Dead stock is easy to spot once you look: nothing has moved for a year. Slow-moving stock is harder, because it still sells — just nowhere near fast enough for the amount you're holding. Here's how to find it in SAP Business One, with a tested query, and what to do with the list.

By SpanMind · Updated November 2026 · Tested on the SAP Business One 10.0 UK demo database · 7 min read

What counts as slow-moving?

Stock that has moved in the last year — so it isn't dead stock — but either:

  • hasn't been issued for 180 days or more, or
  • holds more than 12 months of cover at the rate it sold over the last 12 months.

The second test is the one people miss. An item that sells every week looks healthy in any "last sold" report, but if you hold ten years of it, most of that stock is cash you won't see again for a long time.

Why it's often bigger than dead stock

In SAP's UK demo company (OEC Computers, about £1.9M of stock), dead stock — nothing moved for 12 months — is £219,829. Slow-moving stock, found by the query below, is £1,613,503 across 35 item lines: more than seven times as much.

None of it looks abandoned. A motherboard line has 621 units in stock but sold 34 in the last year — about 219 months, or 18 years, of cover — and it was last delivered six days before the snapshot. A DVD pack line holds 90,156 units against 50,033 sold: almost two years of stock worth £790,986. Every one of these items "sells", so none of them shows up as a problem until you divide stock by demand.

(SAP generates the demo company's data, so the proportions are exaggerated — but the pattern of slow stock hiding behind regular sales is common in real businesses, usually because reorder points and minimums were set for demand that has since dropped.)

Does SAP Business One have a slow-moving report?

Not as a single standard report. The information is in two places: stock and value per warehouse in OITW, and every movement in OINM, the inventory journal. The query below joins them.

The query

SQL Server version

/* Slow-moving stock: moved in the last year, but slowly */
WITH M AS (
    SELECT ItemCode, Warehouse,
        MAX(DocDate) AS LastMovement,
        MAX(CASE WHEN OutQty > 0 AND TransType NOT IN (67, 19, 21, 10000071) THEN DocDate END) AS LastIssue,
        SUM(CASE WHEN TransType NOT IN (67, 19, 21, 10000071) AND DocDate >= DATEADD(MONTH, -12, GETDATE()) THEN OutQty ELSE 0 END) AS Issued12m
    FROM OINM
    WHERE InQty <> 0 OR OutQty <> 0
    GROUP BY ItemCode, Warehouse
)
SELECT TOP 100
    W.ItemCode, I.ItemName, W.WhsCode, W.OnHand, W.StockValue,
    M.LastIssue, DATEDIFF(DAY, M.LastIssue, GETDATE()) AS DaysSinceIssue,
    M.Issued12m,
    CASE WHEN M.Issued12m > 0 THEN CAST(W.OnHand / (M.Issued12m / 12.0) AS DECIMAL(10,1)) END AS MonthsOfCover
FROM OITW W
JOIN OITM I ON I.ItemCode = W.ItemCode
JOIN M ON M.ItemCode = W.ItemCode AND M.Warehouse = W.WhsCode
WHERE W.OnHand > 0 AND I.InvntItem = 'Y'
  AND M.LastMovement >= DATEADD(DAY, -365, GETDATE())
  AND (M.LastIssue IS NULL
    OR M.LastIssue < DATEADD(DAY, -180, GETDATE())
    OR W.OnHand > M.Issued12m)
ORDER BY W.StockValue DESC
SAP HANA version
/* Slow-moving stock: moved in the last year, but slowly */
WITH M AS (
    SELECT "ItemCode", "Warehouse",
        MAX("DocDate") AS "LastMovement",
        MAX(CASE WHEN "OutQty" > 0 AND "TransType" NOT IN (67, 19, 21, 10000071) THEN "DocDate" END) AS "LastIssue",
        SUM(CASE WHEN "TransType" NOT IN (67, 19, 21, 10000071) AND "DocDate" >= ADD_MONTHS(CURRENT_DATE, -12) THEN "OutQty" ELSE 0 END) AS "Issued12m"
    FROM "OINM"
    WHERE "InQty" <> 0 OR "OutQty" <> 0
    GROUP BY "ItemCode", "Warehouse"
)
SELECT
    W."ItemCode", I."ItemName", W."WhsCode", W."OnHand", W."StockValue",
    M."LastIssue", DAYS_BETWEEN(M."LastIssue", CURRENT_DATE) AS "DaysSinceIssue",
    M."Issued12m",
    CASE WHEN M."Issued12m" > 0 THEN CAST(W."OnHand" / (M."Issued12m" / 12.0) AS DECIMAL(10,1)) END AS "MonthsOfCover"
FROM "OITW" W
JOIN "OITM" I ON I."ItemCode" = W."ItemCode"
JOIN M ON M."ItemCode" = W."ItemCode" AND M."Warehouse" = W."WhsCode"
WHERE W."OnHand" > 0 AND I."InvntItem" = 'Y'
  AND M."LastMovement" >= ADD_DAYS(CURRENT_DATE, -365)
  AND (M."LastIssue" IS NULL
    OR M."LastIssue" < ADD_DAYS(CURRENT_DATE, -180)
    OR W."OnHand" > M."Issued12m")
ORDER BY W."StockValue" DESC
LIMIT 100

How it works

  • LastMovement is the latest stock movement of any kind. Lines with nothing in the last 365 days are dead stock and are left out — see the dead stock query for those.
  • LastIssue and Issued12m count real demand only: transfers (67), returns to suppliers (19, 21) and stock-count corrections (10000071) are excluded, so moving stock between warehouses or fixing a count doesn't look like a sale.
  • W.OnHand > M.Issued12m is the "more than 12 months of cover" test: you hold more than you issued in a whole year.
  • MonthsOfCover is stock ÷ average monthly issues. Empty means nothing was issued in 12 months.
  • StockValue is the value B1 itself carries for each item and warehouse, so results sort by cash tied up.

To tighten or loosen it, change 180 (days without an issue) or replace W.OnHand > M.Issued12m with, for example, W.OnHand > M.Issued12m / 2 for six months of cover. The query only reads data; try it in a test company first.

How to read the list

  • High cover, recent sales: the item is fine; the quantity isn't. This is usually a reorder point, minimum or order quantity that was set for higher demand.
  • No issue for 180+ days: demand has stopped or moved to another item or warehouse. Check for a replacement product or a customer you've lost.
  • Never issued, but received in the last year: something was bought that nobody has needed yet — worth a conversation with purchasing.
  • Same item slow in one warehouse, short in another: a transfer releases cash without a sale.

What to do with slow-moving stock

  1. Stop it getting worse. Lower or remove the reorder point and minimum stock on the item, and check MRP isn't still planning for the old demand.
  2. Move it. Transfer to warehouses or branches where it sells.
  3. Sell it down. Bundles, volume pricing, or a push with the customers who still buy it.
  4. Return or swap it. Many suppliers will take back current lines for credit or exchange.
  5. Watch it. Anything that stays slow for another six months is on its way to becoming dead stock.

Skip the SQL

Inventory Doctor flags slow-moving and dead stock from the standard Inventory Audit Report and Inventory Posting List, with months of cover, demand trend, and a suggested action for each line — and you can click any item to see, in plain English, how its stock got there. It's free, and your data never leaves your browser.

FAQ

What's the difference between slow-moving and dead stock?

Dead stock hasn't moved at all for a long time — typically 12 months. Slow-moving stock still moves, but either hasn't been issued for six months or more, or you hold far more of it than you sell.

How are months of cover calculated?

Stock on hand ÷ the average monthly quantity issued over the last 12 months. Transfers, returns to suppliers and stock-count corrections aren't counted as demand.

Does it work on SAP HANA?

Yes — use the HANA version above. It uses the same tables and columns, with HANA's date functions.

Find your slow movers in five minutes

Free inventory health check for SAP Business One. Runs in your browser — nothing is uploaded.

Run the free check