Overview

Learn general aspects of comparison operations.

This section breaks down how CQL evaluates relational operations across different scenarios and operand types.

Operation chaining

Typically, chaining multiple relational operations together is not allowed. That is because the result of the first operation is a boolean, and the second operation expects a number.

However, as in mathematics, CQL allows you to combine two relational operations in an interval-like notation. This is useful when checking whether a value is within a specific range.

For example, the following expression checks whether one value is between two other values, excluding the bounds:

/*<lower-bound>*/ < /*<operand>*/ < /*<upper-bound>*/
Try in Playground

Here is a practical example:

This reads as "x is greater than 1 and less than 3", which is equivalent to:

1 < x and x < 3
Try in Playground

To include the bounds in the range, use the <= and >= operators:

Note that you cannot chain more than two operations together:

1 < 2 < 3 < 4 // 🚨 Invalid
Try in Playground

Chained relational operations inherit the short-circuit optimization from the logical operation. This means that if the left side of the interval is false, the evaluation of the right side is skipped.

For example, consider the following expression:

Since the left side of the interval is false, the right side is not evaluated, making the entire interval false.

As a side note, you can alternatively use the between test to get the same result, but with a more natural language reading:

/*<operand>*/ is between /*<lower-bound>*/ and /*<upper-bound>*/
Try in Playground

General aspects

This section discusses some general aspects of comparison operations.

Equivalence

When comparing two values for equality, CQL follows the general rules of equivalence relations. One of these rules is the transitive property, which states that if a is equal to b and b is equal to c, then a is equal to c.

An example is the best way to illustrate the importance of this property for consistent comparisons:

1 == 1.0 and 1.0 == true and 1 == true
Try in Playground

If you look at the table of equivalence criteria below, you'll see that all three values are equivalent. As a result, the expression evaluates to true.

Here's a summary of the equivalence criteria for each type:

One operandOther operandEquality criteria
StringStringIf both strings are equal, character by character.
StringNullIf the string is empty.
NumberNumberIf both numbers are numerically equal.
NumberBooleanIf the number is equal to 1 for true or 0 for false.
BooleanBooleanIf both booleans are equal.
CollectionCollectionIf both collections contain the same keys and values in the same order.
Local dateLocal dateIf both local dates represent the same day.
Local timeLocal timeIf both local times represent the same time of day.
Local date-timeLocal date-timeIf both date-times represent the same date and time.
InstantInstantIf both instants represent the same point in time.
EnumEnumIf both enums represent the same value.
OtherOtherIf both values are the same type and logically equal.

Note that a local date-time is not equivalent to an instant, since they represent different concepts. The same applies to a local date and a local time.

To compare these values, you must convert them to the same type first. See the conversions section for more information.

Comparability

The relational operations only support a subset of the types available in CQL. More specifically, they only support types that have a concept of order.

Croct's mascot neutral
Don't compare apples and oranges

The operands in a comparison must be comparable. That is, they must be of the same or compatible types (e.g., integers and decimals).

Unlike other operations, relational operations do not attempt to convert the operands to a common type:

"1" > 0 // 🚨 Invalid
Try in Playground

To compare a number and a string, for example, you must either first convert the string to a number or the number to a string:

"1" as number > 0 // ✅ Valid
Try in Playground

The same applies to chronological comparisons:

session's start > "2025-01-01T12:00" as datetime
Try in Playground

This is necessary to ensure you get the expected result. For instance, comparing 10 and 2 as strings would give a different answer than comparing them as numbers. That is why you must convert the operands to a common type first.

The table below lists common types used in comparisons and how they are ordered:

TypeMethodDescription
StringAlphabeticalStrings are ordered alphabetically, character by character, using the lexicographical order.
NumberNumericalNumbers are arranged in standard numerical order, with smaller numbers appearing first.
Date-timeChronologicalDate and time values are ordered chronologically, from the earliest to the latest.