The SN (Structured Numeric) data type was introduced in HL7 v2.3 to give a single field a way to express more than a plain number — a comparator (< 5), a numeric range (5-10), or a ratio (1:160) — without resorting to free text in an NM field. SN appears most often in OBX-5 for structured result values and in lab reference-range slots where the underlying value is intrinsically non-scalar.
Purpose
SN exists because clinical and laboratory results are not always a single number. A titer reported as 1:160, a result reported as < 5, and a tolerance reported as 5-10 are all numerically meaningful but cannot fit into NM. SN structures these into a small, parsable shape that downstream systems can route, threshold, and graph without re-parsing free text. It pairs a comparator with up to two numeric values and a separator that tells a parser whether the dual-value form is a range or a ratio.
Components
Source: HAPI HL7v2 v2.8.1 javadoc (SN). Length is not published in the javadoc (—); required/optional flags reflect typical HL7 v2 conformance use.
| Comp | Name | Sub-type | Length | Required | Description |
|---|---|---|---|---|---|
| SN.1 | Comparator | st | — | O | One of <, <=, >, >=, =, <>. Empty means equality. |
| SN.2 | Num1 | nm | — | O | First numeric value. For a single-value result this is the value; for a range it is the low bound; for a ratio it is the numerator. |
| SN.3 | Separator/Suffix | st | — | O | One of - (range), +, : (ratio), /. Empty when SN.4 is empty. |
| SN.4 | Num2 | nm | — | O | Second numeric value (range high bound or ratio denominator). |
Most-used components
- SN.1 Comparator — the value that makes SN worth using over NM; carries the
</>/>=semantics for detection-limit reporting. - SN.2 Num1 — the primary numeric value; populated in every meaningful SN instance.
- SN.3 Separator/Suffix — disambiguates range (
-) from ratio (:); engines that ignore it cannot tell5-10from5:10. - SN.4 Num2 — the second numeric value required for range and ratio shapes.
Where it's used
- OBX-5 Observation Value when OBX-2 =
SN— structured result values like<^5for "less than 5" or^1^:^160for a titer. - OBX-7 References Range — when a lab transmits a range whose endpoints carry comparators (rare but legal).
- OBR-26 Parent Result child observations that report quantitative thresholds.
- RXE-3 / RXE-6 Give Amount Minimum / Maximum in some local profiles that use SN rather than separate NM fields.
- Reference-range slots in master file (MFN_M08/M09/M10) test definition messages.
- TQ1-3 Repeat Pattern explicit-interval variants in profiles that bind SN.
- Custom OBX panels for serology titers, where SN ratio form is the canonical representation.
Version differences
- HL7 v2.3 — SN introduced with the four-component structure described above.
- HL7 v2.4 through v2.8.1 — no structural changes; the HAPI v2.8.1 javadoc shows the same four components with the same sub-types.
- HL7 v2.8.2 — minor narrative clarifications; component set unchanged.
Common mistakes
- Sending
5^10for a range and omitting SN.3 — without the-separator, parsers cannot distinguish this from "5 then 10 in some unspecified relation" and many will reject it. - Using
~(repetition delimiter) instead of-to separate range endpoints —~is reserved for HL7 field repetition and will fragment the field. - Putting a unit symbol inside SN.2 or SN.4 (e.g.
5 mg) — those components are NM and must be unit-less; units belong in OBX-6. - Sending a comparator in SN.1 and expecting Num2 to mean a range upper bound —
< 5-10is not valid SN; comparators apply to a single numeric shape only. - Locale-formatted decimals (
5,2for5.2) — NM is locale-independent and SN inherits that constraint; downstream parsers will fail on commas.
Examples
Minimal single-value SN (implicit equality):
5
Comparator with a single value (< 5):
<^5^^
Numeric range 5-10:
^5^-^10
Titer ratio 1:160:
^1^:^160
Fully populated edge case — "greater than or equal to 100" with no Num2:
>=^100^^
In context — OBX with a < detection-limit result:
OBX|1|SN|HIV1RNA^HIV-1 RNA quant^L||<^20||copies/mL|<20|N|||F|||20260610141500-0500
In context — OBX serology titer reported as a ratio:
OBX|2|SN|ANA^Antinuclear Ab titer^L||^1^:^160||titer|<1:40|H|||F|||20260610141500-0500
Common pitfall — sending 5-10 as free text inside an NM field instead of SN:
OBX|3|NM|XYZ^Tolerance^L||5-10||mg/dL <- WRONG; NM cannot hold a range
OBX|3|SN|XYZ^Tolerance^L||^5^-^10||mg/dL <- CORRECT
FHIR mapping
The v2-to-FHIR Implementation Guide publishes three per-shape ConceptMaps for SN, one per target FHIR type:
- SN → Quantity — single-value form, where SN.1 maps to
Quantity.comparatorand SN.2 toQuantity.value. - SN → Range — dual-value form with SN.3 =
-; SN.2 →Range.low.value, SN.4 →Range.high.value. - SN → Ratio — dual-value form with SN.3 =
:; SN.2 →Ratio.numerator.value, SN.4 →Ratio.denominator.value.
Picking the target type requires looking at SN.3 before SN.1: a populated separator selects Range or Ratio; an empty separator selects Quantity (with optional comparator).
Engine considerations
- Comparator round-tripping: HAPI v2.8.1 exposes SN.1 as ST, so
<=and>=are preserved verbatim; engines that normalise to single-character comparators silently lose the=and produce semantically different output. - Locale-independent decimals: NM sub-components require a
.decimal separator. Engines running under locales with comma-decimal defaults (de_DE, fr_FR) must explicitly format withLocale.ROOT. - Separator vs. delimiter: SN.3's
^...:...^sequence looks confusing when the component delimiter is also^; renderers must escape consistently and tests should round-trip both range and ratio shapes. - OBX-2 must read
SNfor SN-typed OBX-5; engines that hard-code OBX-2 toNMand then write SN syntax into OBX-5 produce non-conformant messages that strict validators reject.
How Vorro parses and produces SN
On inbound, Vorro decodes SN into a discriminated union: {kind: "value", comparator, value}, {kind: "range", low, high}, or {kind: "ratio", numerator, denominator}. SN.3 is inspected first to pick the shape, then SN.1 is applied for value-shape instances. Comparator strings are preserved verbatim (no normalisation), and NM sub-components are parsed with Locale.ROOT to avoid locale drift. Range invariants (low <= high) are checked and violations raised as soft warnings rather than rejections, because some lab interfaces transmit reversed bounds for descending scales.
On outbound, Vorro renders SN by reconstructing the four components from the typed shape — always writing ^ placeholders for omitted components so column positions stay stable for receivers that split on field index rather than parse strictly.
Related pages
- NM data type — Numeric
- CQ data type — Composite Quantity with Units
- OBX segment — Observation/Result
