Get Help

Differences between systems

Two systems that hold the same data rarely return it the same way. Most of the differences CAT already forgives; the rest you neutralize in the query, on purpose, so a failing comparison means a real difference.

CAT compares values leniently by design — NULL equals NULL, text ignoring case, numbers as numbers within a tolerance, dates as dates; the rules are on Sets match. The table below is what still bites, and the fix for each. The principle throughout: make both sides return the same shape, rather than asking CAT to guess.

Difference What you see Neutralize it
Numeric typesINT vs DECIMAL, FLOAT vs NUMERIC, money as DECIMAL(19,4) vs FLOAT sums off by a cent, 12.5 vs 12.499999 Tolerance: 0.01 (absolute) or Tolerance mode: percent; ROUND(x, 2) on both sides when the tolerance would hide real differences
Dates vs date-timesDATE on one side, DATETIME with midnight on the other compared as dates, usually fine; breaks when the datetime carries a time CAST(… AS DATE) on both sides
Time zones — UTC in the lakehouse, local time in the source every row differs by one or two hours convert in the query (AT TIME ZONE, CONVERT_TZ, from_utc_timestamp) — to UTC on both sides; for watermarks compare dates, not instants
NULL vs empty string — a source that writes '', a warehouse that stores NULL rows differ only in that column NULLIF(col, '') or COALESCE(col, '') on both sides, consistently
Trailing spacesCHAR(n) padding, a source that does not trim 'ABC ' vs 'ABC' — a difference RTRIM / TRIM on both sides
Case'Prague' vs 'PRAGUE' forgiven by default (Ignore case: true) set Ignore case: false when case is the difference you test
Accents and Unicode'Müller' vs 'Muller', precomposed vs decomposed characters differences on names a system-side normalization function, or compare an ASCII-folded column; decide whether it is a real difference first
Booleans1/0 vs true/false vs 'Y'/'N' 1 vs True is a difference (text forms differ, only one reads as a number) CAST to the same type on both sides, or CASE WHEN … THEN 1 ELSE 0 END
Decimal separators and number formats in text'1.234,50' vs 1234.5 text that does not read as a number under the default culture Culture: cs-CZ on the test (also Locale), or cast to a number in the query
GUIDs — braces, case {ABC…} vs abc… — a difference LOWER(CAST(id AS VARCHAR(36))) on both sides
Sort order of text keys — systems sort text by different rules a key “goes backwards” on one side; rows that exist on both sides are reported missing key on a number, a date or an ID; Sort data: true for small sets

Keep it practical

A comparison does not have to be exact to the last byte; it has to run fast and go red only when the data really differs. Pick the cheapest fix from the table that works for your two systems — a cast, a trim, a round, an integer key, a tolerance where the cents do not matter — and move on. You will end up with a handful of such fixes for each pair of systems; reuse them in every comparison between the two.