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>*/
Here is a practical example:
1 < x < 3
This reads as "x is greater than 1 and less than 3", which is equivalent to:
1 < x and x < 3
To include the bounds in the range, use the <= and >= operators:
1 <= 2 < 3
Note that you cannot chain more than two operations together:
1 < 2 < 3 < 4 // 🚨 Invalid
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:
1 < 0 < 3
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>*/
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
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 operand | Other operand | Equality criteria |
---|---|---|
String | String | If both strings are equal, character by character. |
String | Null | If the string is empty. |
Number | Number | If both numbers are numerically equal. |
Number | Boolean | If the number is equal to 1 for true or 0 for false. |
Boolean | Boolean | If both booleans are equal. |
Collection | Collection | If both collections contain the same keys and values in the same order. |
Local date | Local date | If both local dates represent the same day. |
Local time | Local time | If both local times represent the same time of day. |
Local date-time | Local date-time | If both date-times represent the same date and time. |
Instant | Instant | If both instants represent the same point in time. |
Enum | Enum | If both enums represent the same value. |
Other | Other | If 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.
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
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
The same applies to chronological comparisons:
session's start > "2025-01-01T12:00" as datetime
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.
Make sure to convert operands to a compatible type before comparing them since comparing incompatible values will result in an error.
The table below lists common types used in comparisons and how they are ordered:
Type | Method | Description |
---|---|---|
String | Alphabetical | Strings are ordered alphabetically, character by character, using the lexicographical order. |
Number | Numerical | Numbers are arranged in standard numerical order, with smaller numbers appearing first. |
Date-time | Chronological | Date and time values are ordered chronologically, from the earliest to the latest. |