Calculated Fields SQL Reference

LIMS Suite Help
A Calculation field evaluates a SQL expression row-by-row using values from other fields in the same record. The expression must be valid LabKey SQL, but is not a full query — keywords like SELECT, FROM, WHERE, and GROUP BY do not apply here.

Common Expression Examples

GoalExpression
Add two numeric fieldsnumericField1 + numericField2
Subtract two numeric fieldsnumericField1 - numericField2
Multiply two numeric fieldsnumericField1 * numericField2
Divide (denominator never zero)numericField1 / nonZeroField
Divide (denominator might be zero)CASE WHEN denominator <> 0 THEN (numerator / CAST(denominator AS NUMERIC) * 100) ELSE NULL END
Difference in days between two datesTIMESTAMPDIFF('SQL_TSI_DAY', CURDATE(), ExpirationDate)
Date one week after a field valueTIMESTAMPADD('SQL_TSI_WEEK', 1, CollectionDate)
Conditional label based on a numberCASE WHEN FreezeThawCount < 2 THEN 'Viable' ELSE 'Questionable' END
Conditional label based on a text matchCASE WHEN ColorField = 'Blue' THEN 'Abnormal' ELSE 'Normal' END
Concatenate two text fieldsCity || ', ' || State
Concatenate, guarding against NULLsCity || ', ' || COALESCE(State, '')
Field names with special characters"Volume (mL)" + "Buffer Amount"
Fixed text value (e.g. for use with a URL property)'clickMe'
Year extracted from a date fieldYEAR(CollectionDate)
Round a result to 2 decimal placesROUND(Mass / CAST(Volume AS NUMERIC), 2)

Syntax Rules

RuleDetails
Field namesUse the field name directly: Volume. Wrap names that contain spaces or special characters in double quotes: "Volume (mL)", "Field/Name & More".
String literalsUse single quotes: 'Viable'. Escape a single quote inside a string by doubling it: 'Jim''s Sample'.
Case sensitivityField names and function names are case-insensitive.
Date/time literalsUse JDBC escape syntax: {d '2024-01-15'} for a date, {ts '2024-01-15 08:30:00'} for a timestamp.

Operators

Arithmetic Operators

OperatorDescriptionExample
+AddWeight1 + Weight2
-SubtractFinalWeight - TareWeight
*MultiplyConcentration * Volume
/DivideMass / Volume

Integer division truncates. When both operands are integer fields, the result is also an integer. Use CAST to preserve decimal precision:

CAST(NumeratorField AS NUMERIC) / DenominatorField

Dividing by a field that might be zero — guard with CASE to avoid errors:

CASE WHEN Denominator <> 0 THEN (Numerator / CAST(Denominator AS NUMERIC) * 100) ELSE NULL END

String Concatenation

Use || to join text values:

City || ', ' || State

If any operand may be NULL, the result will also be NULL. Wrap nullable fields in COALESCE:

City || ', ' || COALESCE(State, '')

Comparison and Logical Operators

These are used inside CASE expressions and similar conditionals.

OperatorDescription
=Equals
!= or <>Does not equal
<, >, <=, >=Less/greater than (or equal)
IS NULL / IS NOT NULLNull check
BETWEENBetween two values, inclusive. Example: Score BETWEEN 80 AND 90
IN / NOT INMatch against a list. Example: Status IN ('Active', 'Pending')
LIKE / NOT LIKEPattern match. Example: SampleId LIKE 'CTL%'
AND, OR, NOTLogical operators

Conditional Logic — CASE

CASE is the primary tool for branching logic in a calculation expression.

Searched CASE evaluates boolean conditions and returns the result for the first matching branch:

CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ELSE defaultResult END

Example with multiple branches:

CASE WHEN Score >= 90 THEN 'A'
WHEN Score >= 80 THEN 'B'
WHEN Score >= 70 THEN 'C'
ELSE 'F'
END

Simple CASE matches one field against specific values:

CASE Status WHEN 'Active' THEN 1 WHEN 'Pending' THEN 2 ELSE 0 END

The LabKey SQL parser sometimes requires additional parentheses within a CASE statement.

Numeric Functions

FunctionDescriptionExample
ROUND(value, precision)Round to N decimal placesROUND(Mass / Volume, 2)
TRUNCATE(value, precision)Truncate to N decimal places without roundingTRUNCATE(CAST(Temp AS NUMERIC), 1)
ABS(value)Absolute valueABS(Delta)
CEILING(value)Round up to nearest integerCEILING(Volume)
FLOOR(value)Round down to nearest integerFLOOR(Volume)
POWER(base, exponent)Raise to a powerPOWER(Radius, 2)
SQRT(value)Square rootSQRT(Area)
MOD(dividend, divisor)Remainder after divisionMOD(SampleCount, 96)
LOG(n)Natural logarithmLOG(Concentration)
LOG10(n)Base-10 logarithmLOG10(Titer)
EXP(n)e raised to the nth powerEXP(LogValue)
SIGN(value)Returns 1, -1, or 0 based on signSIGN(Delta)

String Functions

FunctionDescriptionExample
CONCAT(a, b)Concatenate two valuesCONCAT(FirstName, LastName)
LENGTH(string)Character countLENGTH(Notes)
SUBSTRING(string, start, length)Extract a substring; start position is 1-basedSUBSTRING(SampleId, 1, 4)
LEFT(string, n)First N charactersLEFT(Barcode, 3)
LCASE(string) / LOWER(string)Convert to lowercaseLCASE(Status)
UCASE(string) / UPPER(string)Convert to uppercaseUCASE(SiteCode)
LTRIM(string)Remove leading whitespaceLTRIM(Label)
RTRIM(string)Remove trailing whitespaceRTRIM(Label)
REPLACE(string, match, replacement)Replace all occurrencesREPLACE(Name, '_', ' ')
LOCATE(substr, string)Position of first match, 1-basedLOCATE('-', SampleId)
STARTSWITH(string, prefix)TRUE if string starts with prefixSTARTSWITH(SampleId, 'CTL')
REPEAT(string, count)Repeat a string N timesREPEAT('X', PadCount)

Date and Time Functions

Extracting Date/Time Parts

FunctionDescriptionExample
CURDATE()Today's date 
NOW()Current date and time 
YEAR(date)Year as integerYEAR(CollectionDate)
MONTH(date)Month as integer (1–12)MONTH(CollectionDate)
MONTHNAME(date)Month name as textMONTHNAME(CollectionDate)
DAYOFMONTH(date)Day of month (1–31)DAYOFMONTH(CollectionDate)
DAYOFWEEK(date)Day of week, where 1=Sunday and 7=SaturdayDAYOFWEEK(CollectionDate)
DAYOFYEAR(date)Day of year (1–365)DAYOFYEAR(CollectionDate)
WEEK(date)Week of year (1–52)WEEK(CollectionDate)
QUARTER(date)Quarter (1–4)QUARTER(CollectionDate)
HOUR(time)Hour componentHOUR(CollectionTime)
MINUTE(time)Minute componentMINUTE(CollectionTime)
SECOND(time)Second componentSECOND(CollectionTime)

Date Arithmetic

TIMESTAMPDIFF(interval, timestamp1, timestamp2) finds the difference between two dates at a specified interval:

TIMESTAMPDIFF('SQL_TSI_DAY', CURDATE(), ExpirationDate)
TIMESTAMPDIFF('SQL_TSI_HOUR', StartTime, EndTime)

TIMESTAMPADD(interval, n, timestamp) adds an interval to a date:

TIMESTAMPADD('SQL_TSI_WEEK', 1, CollectionDate)
TIMESTAMPADD('SQL_TSI_MONTH', 6, StorageDate)

Available interval values for both functions:

IntervalUnit
'SQL_TSI_FRAC_SECOND'Fractional seconds
'SQL_TSI_SECOND'Seconds
'SQL_TSI_MINUTE'Minutes
'SQL_TSI_HOUR'Hours
'SQL_TSI_DAY'Days
'SQL_TSI_WEEK'Weeks
'SQL_TSI_MONTH'Months
'SQL_TSI_QUARTER'Quarters
'SQL_TSI_YEAR'Years

PostgreSQL note: TIMESTAMPDIFF does not support SQL_TSI_FRAC_SECOND, SQL_TSI_WEEK, SQL_TSI_MONTH, SQL_TSI_QUARTER, or SQL_TSI_YEAR. Use the age functions for month/year differences:

  • AGE_IN_MONTHS(date1, date2)
  • AGE_IN_YEARS(date1, date2)

NULL Handling

FunctionDescriptionExample
COALESCE(val1, val2, ...)Returns the first non-NULL value in the listCOALESCE(FinalVolume, EstimatedVolume, 0)
IFNULL(value, default)Returns the default if value is NULLIFNULL(Units, 0)
NULLIF(a, b)Returns NULL if a equals b, otherwise returns aNULLIF(ErrorCode, 0)
ISEQUAL(a, b)TRUE if a equals b, or if both are NULLISEQUAL(StatusA, StatusB)

Type Casting

Use CAST to convert a value to a specific data type. This is especially important when dividing integer fields — without casting, LabKey SQL returns a truncated integer result.

CAST(TextField AS INTEGER)
CAST(IntegerField AS NUMERIC)
CAST(DateTimeField AS DATE)
CAST(NumberField AS VARCHAR)
CAST(Value AS NUMERIC(10, 2))

Common cast targets: INTEGER, NUMERIC, DECIMAL, FLOAT, DOUBLE, VARCHAR, DATE, TIMESTAMP, BIGINT, SMALLINT

Was this content helpful?

Log in or register an account to provide feedback


previousnext
 
expand allcollapse all