The following are the built-in comparison operators available in the MSQL language. They are divided into the following groups:
=, <>, <, >, <=, >=
, BETWEEN
and IS [NOT] DISTINCT FROM
operators.NULL
and truth-value testing operators IS [NOT] NULL
, IS [NOT] TRUE
and IS [NOT] FALSE
.LIKE
and SIMILAR TO
comparisons.CONTAINS
, COVERS
, COVEREDBY
, CROSSES
, DISJOINT
, EQUALS
, INTERSECTS
, OVERLAPS
, TOUCHES
, WITHIN
, [IMMEDIATELY] PRECEDES/SUCCEEDS
.(a: T) = (b: T) -> bool
(a: T) <> (b: T) -> bool
(a: T) != (b: T) -> bool
(a: T) < (b: T) -> bool
(a: T) <= (b: T) -> bool
(a: T) > (b: T) -> bool
(a: T) >= (b: T) -> bool
Returns the result of comparison between two values.
Arguments
Both operands must be of the same type family (e.g. numeric, character). Comparisons of spatial operands are not supported.
Null handling
If any of the operands is NULL
, the result of the comparison will be NULL
, regardless of the value of the other operand. It means that even NULL = NULL
and 7 <> NULL
will return NULL
instead of true
, which, even though consistent with MSQL's three-valued logic, presents a common pitfail for inexperienced SQL users.
Notes
Operator !=
is just an alias for <>
, for users who are more accustomed to writing !=
for testing non-equality.
Examples
SELECT x = y, x <> y, x < y, x <= y, x > y, x >= y
FROM (VALUES (4, 7), (-5, -5)) AS t(x, y);
--> +-------+-------+-------+------+-------+-------+
--> | = | <> | < | <= | > | >= |
--> +-------+-------+-------+------+-------+-------+
--> | false | true | true | true | false | false |
--> | true | false | false | true | false | true |
--> +-------+-------+-------+------+-------+-------+
See also
(x: T) BETWEEN (a: T) AND (b: T) -> bool
(x: T) NOT BETWEEN (a: T) AND (b: T) -> bool
Checks whether the value of x
is between given bounds (bounds are inclusive).
Notes
These operators are just a shorthand way of writing the equivalent comparisons by hand:
x BETWEEN a AND b <-> x >= a AND x <= b
x NOT BETWEEN a AND b <-> x < a OR x > b
All the issues with NULL
values mentioned above when describing basic comparisons apply here as well.
Examples
SELECT 10 BETWEEN 5 AND 100;
--> true
SELECT 10 NOT BETWEEN 1 AND 10;
--> false
See also
(a: T) IS DISTINCT FROM (b: T) -> bool
(a: T) IS NOT DISTINCT FROM (b: T) -> bool
(a: T) <=> (b: T) -> bool
Checks whether the two operands have the same value or not.
Notes
For non-null inputs, IS DISTINCT FROM
is the same as the <>
operator, and IS NOT DISTINCT FROM
the same as the operator =
.
However, if both inputs are null, IS DISTINCT FROM
returns false
, and IS NOT DISTINCT FROM
returns true
.
When only one input is null, IS DISTINCT FROM
return true
, and IS NOT DISTINCT FROM
returns false
.
Neither operator ever returns NULL
, under any conditions.
The a <=> b
is equivalent to a IS NOT DISTINCT FROM b
.
These predicates effectively act as if NULL
were a normal data value, rather than representing an unknown/missing value.
Examples
SELECT 'abc' IS DISTINCT FROM NULL::text;
--> true
SELECT NULL::int64 IS NOT DISTINCT FROM NULL::int64;
--> true
SELECT 'abc' <=> 'abc';
--> true
See also
(x: T) IS NULL -> bool
(x: T) IS NOT NULL -> bool
Checks whether the given operand is equal to NULL
.
Notes
The IS NULL
and IS NOT NULL
operators must be used instead of x = NULL
or x <> NULL
, which are incorrect because one NULL
value is not equal to another NULL
value. That is so because NULL
represents an unknown/missing value, and it is not known (in the query evaluation context) whether two NULL
s represent the same value.
Examples
SELECT NULL IS NULL;
--> true
SELECT 10 IS NOT NULL;
--> true
See also
(x: bool) IS TRUE -> bool
(x: bool) IS NOT TRUE -> bool
Checks whether a given boolean expression is true.
Notes
These operators always return true
or false
, never NULL
, even when the operand evaluates to NULL
.
These operators can be useful for special handling of NULL
values in boolean contexts, e.g. in filter or join conditions.
Examples
SELECT false IS TRUE;
--> false
SELECT NULL IS NOT TRUE;
--> true
See also
(x: bool) IS FALSE -> bool
(x: bool) IS NOT FALSE -> bool
Checks whether a given boolean expression is false.
Notes
These operators always return true
or false
, never NULL
, even when the operand evaluates to NULL
.
These operators can be useful for special handling of NULL
values in boolean contexts.
For example, NULL
s in the WHERE
clause behave the same as false
(i.e. the rows are dropped), but if this isn't desired, the IS NOT FALSE
operator could be applied to fix it.
Examples
SELECT true IS FALSE;
--> false
SELECT NULL IS NOT FALSE;
--> true
See also
(x: text) LIKE (p: text) -> bool
(x: text) NOT LIKE (p: text) -> bool
(x: text) LIKE (p: text) ESCAPE e -> bool
(x: text) NOT LIKE (p: text) ESCAPE e -> bool
Tests whether a character string (first operand) matches a given pattern (second operand).
Null handling
If any of the operands is NULL
, the result will also be NULL
.
Notes
A pattern can contain arbitrary characters, which all match only themselves (e.g. letter a
in the pattern would match exactly one letter a
in the string), except for two special characters: underscore _
and percent-sign %
. The underscore _
in a pattern stands for any single character, and the percent-sign %
matches any sequence of zero or more characters.
To match a literal underscore or percent-sign character instead of a wildcard, the character should be escaped by an escape character (the default is backspace '\'
). A different escape character can be chosen by appending the ESCAPE
clause to the LIKE
operator (e.g. x LIKE 'C:$\Documents$\%' ESCAPE '$'
). To match the escape character itself, two escape characters should be used (i.e. '\\'
).
The backslash (\
) itself must be escaped in character string literals (as it also is used for specifying Unicode escape sequences), therefore matching a literal backslash by the LIKE
operator (when the default escape character is used) must be done as x LIKE '%\\\\%'
.
The character matching is case-sensitive. If a case-insensitive match is needed, it can be accomplished by first converting the input to lowercase (or uppercase) using the LOWER or UPPER functions, e.g. by specifying LOWER(x) LIKE '%stuff%'
.
LIKE
pattern matching always tries to cover the entire string. Therefore, if just a subsequence of it needs to be matched, the pattern should start and end with a %
sign (e.g. finding 'abc'
anywhere in the string -> x LIKE '%abc%'
).
Examples
SELECT s
FROM (VALUES 'abc', 'ABC', 'abracadabra', 'banana', 'abacus') AS t(s)
WHERE s LIKE 'ab%';
--> +---------------+
--> | s |
--> +---------------+
--> | 'abc' |
--> | 'abracadabra' |
--> | 'abacus' |
--> +---------------+
SELECT s
FROM (VALUES 'asterix', 'boar', 'obelix', 'taxi') AS t(s)
WHERE s NOT LIKE '%x';
--> +--------+
--> | s |
--> +--------+
--> | 'boar' |
--> | 'taxi' |
--> +--------+
(x: text) SIMILAR TO (p: text) -> bool
(x: text) NOT SIMILAR TO (p: text) -> bool
(x: text) SIMILAR TO (p: text) ESCAPE e -> bool
(x: text) NOT SIMILAR TO (p: text) ESCAPE e -> bool
Tests whether a character string (first operand) matches a given POSIX regular-expression pattern (second operand).
Null handling
If any of the operands is NULL
, the result will also be NULL
.
Notes
This operator is not yet supported!
(v1: T1) @> (v2: T2) -> bool
(v1: T1) CONTAINS (v2: T2) -> bool
Returns true if one range/value wholly contains another range/value. In case of spatial operands, it's an alias for ST_CONTAINS function.
Arguments
The arguments must both be geometries or ranges, or a range and a corresponding numeric/timepoint value.
Notes
a CONTAINS b
is equivalent to b WITHIN a
.
Examples
SELECT RANGE(0, 20) @> RANGE(10, 15);
--> true
SELECT RANGE(0, 20) CONTAINS RANGE(10, 25);
--> false
SELECT RANGE(0, 20) @> 15;
--> true
SELECT RANGE(0, 20) CONTAINS 25;
--> false
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0))' @> linestring '(5 0, 15 0, 15 10)';
--> true
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0), (5 5, 10 10, 15 5, 5 5))' CONTAINS multipoint '(2 2, 10 8)';
--> false
See also
(g1: anygeometry) #> (g2: anygeometry) -> bool
(g1: anygeometry) COVERS (g2: anygeometry) -> bool
Alias for the ST_COVERS function.
Examples
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0))' COVERS point '(10 0)';
--> true
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0), (5 5, 15 5, 10 10, 5 5))' #> linestring '(5 0, 10 0, 10 20)';
--> false
(g1: anygeometry) <# (g2: anygeometry) -> bool
(g1: anygeometry) COVEREDBY (g2: anygeometry) -> bool
Alias for the ST_COVEREDBY function.
Examples
SELECT point '(10 0)' COVEREDBY polygon '((0 0, 20 0, 20 20, 0 20, 0 0))';
--> true
SELECT linestring '(5 0, 10 0, 10 20)' <# polygon '((0 0, 20 0, 20 20, 0 20, 0 0), (5 5, 15 5, 10 10, 5 5))';
--> false
(g1: anygeometry) -|- (g2: anygeometry) -> bool
(g1: anygeometry) CROSSES (g2: anygeometry) -> bool
Alias for the ST_CROSSES function.
Examples
SELECT linestring '(0 0, 10 0, 20 10)' CROSSES linestring '(0 10, 20 0)';
--> true
SELECT multipoint '(10 10, 20 20)' -|- polygon '((0 0, 20 0, 20 20, 0 20, 0 0))';
--> false
(v1: T1) !&& (v2: T2) -> bool
(v1: T1) DISJOINT (v2: T2) -> bool
Returns true if the two ranges (or a range and a value) are completely disjoint. In case of spatial operands, it's an alias for ST_DISJOINT function.
Arguments
The arguments must both be geometries or ranges, or a range and a corresponding numeric/timepoint value.
Notes
a DISJOINT b
is equivalent to !(a INTERSECTS b)
.
Examples
SELECT RANGE(0, 20) !&& RANGE(30, 40);
--> true
SELECT RANGE(0, 20) DISJOINT RANGE(10, 40);
--> false
SELECT RANGE(0, 20) !&& 30;
--> true
SELECT RANGE(0, 20) DISJOINT 10;
--> false
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0))' DISJOINT point '(30 40)';
--> true
SELECT point '(0 0)' !&& linestring '(0 0, 10 10)';
--> false
See also
(v1: T1) ~= (v2: T2) -> bool
(v1: T1) EQUALS (v2: T2) -> bool
Returns true if the two ranges (or a range and a value) contain all the same values. In case of spatial operands, it's an alias for ST_EQUALS function.
Arguments
The arguments must both be geometries or ranges, or a range and a corresponding numeric/timepoint value.
Notes
The ranges are equal if both their lower bounds and upper bounds are equal, i.e. if LBOUND(r1) = LBOUND(r2) AND RBOUND(r1) = RBOUND(r2)
.
Examples
SELECT RANGE(10, 20) ~= RANGE(20, 10);
--> true
SELECT RANGE(10, 20) EQUALS RANGE(30, 10);
--> false
SELECT RANGE(10, 10) ~= 10;
--> true
SELECT RANGE(10, 20) EQUALS 10;
--> false
SELECT linestring '(0 0, 5 5, 10 10)' EQUALS linestring '(10 10, 0 0)';
--> true
SELECT linestring '(0 0, 20 0, 20 20, 0 20, 0 0)' ~= linestring '(0 0, 20 20, 20 0, 0 20, 0 0)';
--> false
See also
(v1: T1) && (v2: T2) -> bool
(v1: T1) INTERSECTS (v2: T2) -> bool
Returns true if the two ranges (or a range and a value) intersect. In case of spatial operands, it's an alias for ST_INTERSECTS function.
Arguments
The arguments must both be geometries or ranges, or a range and a corresponding numeric/timepoint value.
Notes
a INTERSECTS b
is equivalent to !(a DISJOINT b)
.
Examples
SELECT RANGE(0, 20) && RANGE(10, 40);
--> true
SELECT RANGE(0, 20) INTERSECTS RANGE(30, 40);
--> false
SELECT RANGE(0, 20) && 10;
--> true
SELECT RANGE(0, 20) INTERSECTS 30;
--> false
SELECT linestring '(0 0, 10 10)' INTERSECTS point '(5 5)';
--> true
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0))' && point '(30 40)';
--> false
See also
(v1: T1) <@> (v2: T2) -> bool
(v1: T1) OVERLAPS (v2: T2) -> bool
Returns true if the two ranges overlap, i.e. they intersect and their intersection is not just a single point. In case of spatial operands, it's an alias for ST_OVERLAPS function.
Arguments
The arguments must both be geometries or ranges, or a range and a corresponding numeric/timepoint value.
Notes
If the arguments are a range and a single value, the result will always be false
.
Examples
SELECT RANGE(0, 20) <@> RANGE(10, 40);
--> true
SELECT RANGE(0, 20) OVERLAPS RANGE(20, 40);
--> false
SELECT RANGE(0, 20) <@> 10;
--> false
SELECT RANGE(0, 20) OVERLAPS 20;
--> false
SELECT linestring '(0 10, 0 0, 10 0, 10 10)' OVERLAPS linestring '(0 -10, 0 0, 10 0, 10 -10)';
--> true
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0))' <@> linestring '(10 10, 30 30)';
--> false
See also
(v1: T1) >|< (v2: T2) -> bool
(v1: T1) TOUCHES (v2: T2) -> bool
Returns true if the two ranges (or a range and a value) touch at a single point. In case of spatial operands, it's an alias for ST_TOUCHES function.
Arguments
The arguments must both be geometries or ranges, or a range and a corresponding numeric/timepoint value.
Examples
SELECT RANGE(0, 10) >|< RANGE(10, 20);
--> true
SELECT RANGE(0, 12) TOUCHES RANGE(10, 20);
--> false
SELECT RANGE(0, 10) >|< 10;
--> true
SELECT RANGE(0, 12) TOUCHES 10;
--> false
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0))' TOUCHES polygon '((20 5, 30 5, 30 15, 20 15, 20 5))';
--> true
SELECT polygon '((0 0, 20 0, 20 20, 0 20, 0 0))' >|< linestring '(10 10, 30 30)';
--> false
See also
(v1: T1) <@ (v2: T2) -> bool
(v1: T1) WITHIN (v2: T2) -> bool
Returns true if one range/value is wholly contained within another range/value. In case of spatial operands, it's an alias for ST_WITHIN function.
Arguments
The arguments must both be geometries or ranges, or a range and a corresponding numeric/timepoint value.
Notes
a WITHIN b
is equivalent to b CONTAINS a
.
Examples
SELECT RANGE(10, 15) <@ RANGE(0, 20);
--> true
SELECT RANGE(10, 25) WITHIN RANGE(0, 20);
--> false
SELECT 15 <@ RANGE(0, 20);
--> true
SELECT 25 WITHIN RANGE(0, 20);
--> false
SELECT linestring '(5 0, 15 0, 15 10)' WITHIN polygon '((0 0, 20 0, 20 20, 0 20, 0 0))';
--> true
SELECT multipoint '(10 0, 0 10, 20 20)' <@ polygon '((0 0, 20 0, 20 20, 0 20, 0 0), (5 5, 15 5, 10 10, 5 5))';
--> false
See also
(v1: T1) <<- (v2: T) -> bool
(v1: T1) PRECEDES (v2: T2) -> bool
Returns true if one range/value is completely to the left of another range/value.
Arguments
The arguments must both be ranges, or a range and a corresponding numeric/timepoint value.
Notes
The range r1
is completely on the left of range r2
if it holds that RBOUND(r1) <= LBOUND(r2)
.
a PRECEDES b
is equivalent to b SUCCEEDS a
.
Examples
SELECT RANGE(0, 10) <<- RANGE(20, 30);
--> true
SELECT RANGE(0, 25) PRECEDES RANGE(20, 30);
--> false
SELECT 10 <<- RANGE(20, 30);
--> true
SELECT RANGE(0, 25) PRECEDES 20;
--> false
See also
(v1: T1) <<| (v2: T) -> bool
(v1: T1) IMMEDIATELY PRECEDES (v2: T2) -> bool
Returns true if one range/value is immediately to the left of another range/value.
Arguments
The arguments must both be ranges, or a range and a corresponding numeric/timepoint value.
Notes
The range r1
is immediately on the left of range r2
if it holds that RBOUND(r1) = LBOUND(r2)
.
a IMMEDIATELY PRECEDES b
is equivalent to b IMMEDIATELY SUCCEEDS a
.
Examples
SELECT RANGE(0, 20) <<| RANGE(20, 30);
--> true
SELECT RANGE(0, 10) IMMEDIATELY PRECEDES RANGE(20, 30);
--> false
SELECT 20 <<| RANGE(20, 30);
--> true
SELECT RANGE(0, 10) IMMEDIATELY PRECEDES 30;
--> false
See also
(v1: T1) ->> (v2: T) -> bool
(v1: T1) SUCCEEDS (v2: T2) -> bool
Returns true if one range/value is completely to the right of another range/value.
Arguments
The arguments must both be ranges, or a range and a corresponding numeric/timepoint value.
Notes
The range r1
is completely on the right of range r2
if it holds that LBOUND(r1) >= RBOUND(r2)
.
a SUCCEEDS b
is equivalent to b PRECEDES a
.
Examples
SELECT RANGE(35, 40) ->> RANGE(20, 30);
--> true
SELECT RANGE(25, 40) SUCCEEDS RANGE(20, 30);
--> false
SELECT 40 ->> RANGE(20, 30);
--> true
SELECT RANGE(25, 40) SUCCEEDS 30;
--> false
See also
(v1: T1) |>> (v2: T) -> bool
(v1: T1) IMMEDIATELY SUCCEEDS (v2: T2) -> bool
Returns true if one range/value is immediately to the right of another range/value.
Arguments
The arguments must both be ranges, or a range and a corresponding numeric/timepoint value.
Notes
The range r1
is immediately on the right of range r2
if it holds that LBOUND(r1) = RBOUND(r2)
.
a IMMEDIATELY SUCCEEDS b
is equivalent to b IMMEDIATELY PRECEDES a
.
Examples
SELECT RANGE(30, 40) |>> RANGE(20, 30);
--> true
SELECT RANGE(35, 40) IMMEDIATELY SUCCEEDS RANGE(20, 30);
--> false
SELECT 30 |>> RANGE(20, 30);
--> true
SELECT RANGE(35, 40) IMMEDIATELY SUCCEEDS 30;
--> false
See also