Project: YugabyteDB (App Definition and Development / Database)
File: comparison.md

title: Array comparison linkTitle: Array comparison headerTitle: Operators for comparing two arrays description: Operators for comparing two arrays menu: v2.18: identifier: array-comparison parent: array-functions-operators weight: 20 type: docs Purpose: Each of the comparison operators returns `TRUE` or `FALSE` according to the outcome of the particular comparison test between the input arrays. Signature These operators all have the same signature, thus: ``` input value: anyarray, anyarray return value: boolean ``` Note: These operators require that the LHS and RHS arrays have the same data type. (It's the same rule for the comparison of scalars.) However, they do not require that the arrays have identical geometric properties. Rules are defined so that a difference between one or more of these properties does not mean that comparison is disallowed. Rather, the LHS array might be deemed to be less than, or greater than, the RHS array. It's essential, therefore, to understand the comparison algorithm. These are the unique characteristics of an array with respect to the algorithm that compares two array values: the actual values, compared pairwise in row-major order the cardinality the number of dimensions the lower bound on each dimension. The term "row-major order" is explained in within the section "Functions for reporting the geometric properties of an array". The other geometric properties (the length and upper bound along each dimension) can be derived from the properties that the bullets list.. There is, of course, a well-defined priority among the comparisons. Briefly, value comparison is done first. Then, but only if no difference is detected, are the geometric properties compared. The first comparison test scans the values in each of the LHS and RHS arrays in row-major order (see ) and does a pairwise comparison. Notably, the comparison rule non-negotiably uses `IS NOT DISTINCT FROM` semantics. Moreover, when a `not null` array value is pairwise compared with a `NULL` value, the `not null` value is deemed to be less than the `NULL` value. Notice the contrast with the `=` operator comparison rule for free-standing scalar values. This comparison uses `NULL` semantics but, of course, lets you use `IS NOT DISTINCT FROM` comparison if this better suits your purpose. Otherwise, the comparison rules are the same as those for scalar values and, by extension, with those for, for example, "row" type values. If a pairwise comparison results in inequality, then the LHS and RHS arrays are immediately deemed to be unequal with no regard to the geometric properties. The outcome of the first pairwise comparison, when these values differ, determines the outcome of the array comparison. Remaining pairwise comparisons are not considered. Notice that the two arrays might not have the same cardinality. If all possible pairwise comparisons result in equality, then the array with the greater cardinality is deemed to be greater than the other array, and the other geometric properties are not considered. The previous section stated the rule that the cardinality comparison has the highest priority among the geometric property comparisons. And that this rule kicks in only of all possible value comparisons result in equality. When both all possible value comparisons and the cardinality comparison result in equality, then the comparison between the number of dimensions has a higher priority than the comparison between the lower bound on each

Of course, the array with the greater number of dimensions is deemed to be the greater array. This means that the lower bounds are significant when two arrays are compared only when they are identical in pairwise value comparison, cardinality, and the number of dimensions. Then the array with the greater lower bound, in dimension order, is deemed to be the greater array. demonstrates each of the rules that this "Comparison operators overview" section has stated. These three operators are insensitive to the geometric properties of the two to-be-compared arrays. The two containment operators test if the distinct set of values in one array contains, or is contained by, the distinct set of values in the other array. The overlap operator tests if the distinct set of values in one array and the distinct set of values in the other array have at least one value in common. below demonstrates each of the rules that this section has stated. The `=` operator returns `TRUE` if the LHS and RHS arrays are equal. The `<>` operator is the natural complement: it returns `TRUE` if the LHS and RHS arrays are not equal. ```plpgsql with v as ( select (select array['a', 'b', null, 'd']::text[]) as a1, (select '{a, b, null, d}'::text[]) as a2 ) select (a1 = a2)::text as "EQUALITY comparison result" from v; ``` This is the result: ``` EQUALITY comparison result true ``` ```plpgsql with v as ( select (select array['a', 'b', 'c', 'd']::text[]) as a1, (select '{a, b, null, d}'::text[]) as a2 ) select (a1 <> a2)::text as "INEQUALITY comparison result" from v; ``` This is the result: ``` INEQUALITY comparison result true ``` These four operators implement the familiar inequality comparisons. The `>` operator returns `TRUE` if the LHS array is greater than the RHS array. The `>=` operator returns `TRUE` if the LHS array is greater than or equal to the RHS array. The `<=` operator returns `TRUE` if the LHS array is less than or equal to the RHS array. The `<` operator returns `TRUE` if the LHS array is less than the RHS array. It's sufficient, therefore, to provide an example for just the `<` operator. ```plpgsql with v as ( select (select array['a', 'b', 'c', 'd']::text[]) as a1, (select array['a', 'b', 'e', 'd']::text[]) as a2, (select '{a, b, null, d}'::text[]) as a3 ) select (a1 < a2)::text as "'LESS THAN' comparison result 1", (a1 < a3)::text as "'LESS THAN' comparison result 2" from v; ``` This is the result: ``` 'LESS THAN' comparison result 1 | 'LESS THAN' comparison result 2 true | true ``` The `@>` operator returns `TRUE` if the LHS array contains the RHS arraythat is, if every distinct value in the RHS array is found among the LHS array's distinct values. The `<@` operator is the natural complement: it returns `TRUE` if every distinct value in the LHS array is found among the RHS array's distinct

```plpgsql with v as ( select (select array['a', 'b', 'c', 'd']::text[]) as a1, (select array['a', 'c' ]::text[]) as a2 ) select (a1 @> a2)::text as "CONTAINS comparison result", (a2 <@ a1)::text as "'IS CONTAINED BY' comparison result" from v; ``` This is the result: ``` CONTAINS comparison result | 'IS CONTAINED BY' comparison result -+- true | true ``` The `&&` operator returns `TRUE` if the LHS and RHS arrays overlapthat is, if they have at least one value in common. The definition of this operator makes it insensitive to which of the two to-be-compared is used on the LHS and which is used on the RHS. ```plpgsql with v as ( select (select array['a', 'b', 'c', 'd']::text[]) as a1, (select array['d', 'e', 'f', 'g']::text[]) as a2 ) select (a1 && a2)::text as "'a1 OVERLAPS a2' comparison result", (a2 && a1)::text as "'a2 OVERLAPS a1' comparison result" from v; ``` This is the result: ``` 'a1 OVERLAPS a2' comparison result | 'a2 OVERLAPS a1' comparison result true | true ``` This section demonstrates each of the rules that above stated. ```plpgsql -- Any two arrays can be compared without error if they have the same data type. do $body$ begin -- Illustrate "IS NOT DISTINCT FROM" semantics. declare v1 constant int := 1; v2 constant int := 1; n1 constant int := null; n2 constant int := null; begin assert (v1 = v2) and (v1 is not distinct from v2) and ((n1 = n2) is null) and (n1 is not distinct from n2), 'unexpected'; end; -- Basic demonstration of equaliy when the geom. properties of -- the two arrays are identical. -- Shows that pairwise comparison uses "IS NOT DISTINCT FROM" semantics and NOT -- the conventional NULL semantics used when scalars are compared. declare a constant int[] := '{10, null, 30}'; b constant int[] := '{10, null, 30}'; -- Identical to a. begin assert (a = b), '"a = b" assert failed'; -- Because of this, there's no need ever to write this. assert (a is not distinct from b), '"a is not distinct from b" assert failed'; end; -- Basic demonstration of inequality when the geometric properties of -- the two arrays are identical. -- When the first difference is encountered in row-major order, the comparison -- is made. Other differences are irrelevant. declare a constant int[] := '{10, 20, 30}'; b constant int[] := '{10, 19, 31}'; begin assert (a <> b) and (a > b) and (a >= b) and (b <= a) and (b < a) , '"a > b" assert failed'; end; -- Demonstration of inequality when the geometric properties of -- the two arrays are identical. -- Here, the first pairwise difference is NOT NULL versus NULL. declare a constant int[] := '{10, 20, 30}'; b constant int[] := '{10, null, 29}'; begin -- Bizarrely, a NOT NULL value counts as LESS THAN a NULL value in the -- pairwise comparison. assert (a <> b) and (a < b), '"a < b" assert failed'; -- Again, because of this, there's no need ever to write this. assert (a is distinct from b) , '"a is distinct from b" assert failed'; end; -- Extreme demonstration of priority. -- c has just a single value and d has several. -- c has one dimension and d has two. -- c's first lower bound is less than d's first lower. -- d's second lower bound is greater than one, but is presumably irrelevant. -- But c's first value is GREATER THAN d's first value, -- scanning in row-major order. -- -- Pairwise value comparison has the hoghest

-- therefore c is deemed to be GREATER THAN d. declare c constant int[] := '{2}'; -- Notice that d's first value is at . d constant int={{1, 2}, {3, 3}}'; begin assert cardinality(c) < cardinality(d), '"cardinality(c) < cardinality(d)" assert failed'; assert arrayndims(c) < arrayndims(d), '"ndims(c) < ndims(d)" assert failed'; assert arraylower(c, 1) < arraylower(d, 1), '"lower(c, 1) < lower(d, 1)" assert failed'; assert c, '"c" assert failed'; assert c > d, '"c > d" assert failed'; end; -- Pairwise comparison is equal are far as it is feasible. -- e's ndims < f's. -- e's lb-1 < f's. -- BUT e's cardinality > f's. -- Cardinality has highest priority among the geom. propoerties, -- so e is deemed to be GREATER THAN f. declare e constant int[] := '{10, 20, 30, 40, 50, 60, 70}'; f constant int={{10, 20, 30}, {40, 50, 60}}'; begin assert e and e and e and e and e and e , '"e-to-f" eqality test, as far as feasible, assert failed'; assert arrayndims(e) < arrayndims(f), '"ndims(e) < ndims(f)" assert failed'; assert arraylower(e, 1) < arraylower(f, 1), '"lower(e, 1) < lower(f, 1)" assert failed'; assert cardinality(e) > cardinality(f), '"cardinality(e) > cardinality(f)" assert failed'; assert (e > f) , 'e > f assert failed'; end; -- g's cardinality = h's. -- So pairwise comparison is feasible for all values, and is equal. -- g's ndims > h's. -- g's lb-1 < h's. -- Ndims has higher priority among ndims and lower bounds, -- so g is deemed to be GREATER THAN h. declare g constant int[] := '{{10, 20, 30}, {40, 50, 60}}'; h constant int[] := '[2:7]={10, 20, 30, 40, 50, 60}'; begin assert cardinality(g) = cardinality(h), '"cardinality(g) = cardinality(h)" assert failed'; assert g = h[2] and g = h[3] and g = h[4] and g = h[5] and g = h[6] and g = h[7] , '"g-to-h" eqality test assert failed'; assert arrayndims(g) > arrayndims(h), '"ndims(g) > ndims(h)" assert failed'; assert arraylower(g, 1) < arraylower(h, 1), '"lower(g, 1) < lower(h, 1)" assert failed'; assert (g > h) , '"g > h" assert failed'; end; declare i constant int={{10, 20, 30}, {40, 50, 60}}'; j constant int={{10, 20, 30}, {40, 50, 60}}'; begin assert cardinality(i) = cardinality(j), '"cardinality(i) = cardinality(j)" assert failed'; assert i = j and i = j and i = j and i = j and i = j and i = j , '"i-to-j" eqality test assert failed'; assert arrayndims(i) = arrayndims(j), '"ndims(i) = ndims(j)" assert failed'; assert arraylower(i, 1) > arraylower(j, 1), '"lower(i, 1) > lower(j, 1)" assert failed'; assert (i > j) , '"i > j" assert failed'; end; end; $body$; ``` This section demonstrates each of the rules that stated. ```plpgsql -- Any two arrays can be compared without error if they have the same data type. -- Insensitive to the geometric properties. do $body$ declare a constant int={{10, 20}, {30, 40}}'; b constant int[] := '[5:6]={20, 30}'; c constant int[] := '[6:9]={40, 50, 70, 70}'; d constant int[] := '[2:4]={50, 60, 70}'; begin assert -- Containment (b @> b) and (b <@ a) and -- Overlap. -- The definition of the semantics makes the LHS, RHS order immaterial. (a && c) and (c && a) and -- a and d have NO values in common. not (a && d), 'unexpected'; end; $body$; ```