create or replace function range_exclude(anyelement, anyelement) returns anyarray as $$
declare
r1 text;
r2 text;
begin
-- Check input parameters
if not pg_typeof($1) in ('numrange'::regtype, 'int8range'::regtype, 'daterange'::regtype, 'tstzrange'::regtype) then
raise exception 'Function accepts only range types but got % type.', pg_typeof($1);
end if;
-- If result is single element
if ($1 &< $2 or $1 &> $2) then
return array[$1 - $2];
end if;
-- Else build array of two intervals
if lower_inc($1) then r1 := '['; else r1 := '('; end if;
r1 := r1 || lower($1) || ',' || lower($2);
if lower_inc($2) then r1 := r1 || ')'; else r1 := r1 || ']'; end if;
if upper_inc($2) then r2 := '('; else r2 := '['; end if;
r2 := r2 || upper($2) || ',' || upper($1);
if upper_inc($1) then r2 := r2 || ']'; else r2 := r2 || ')'; end if;
return array[r1, r2];
end $$ immutable language plpgsql;
create or replace function range_exclude(anyelement, anyarray) returns anyarray as $$
declare
i int;
j int;
begin
-- Check input parameters
if not pg_typeof($1) in ('numrange'::regtype, 'int8range'::regtype, 'daterange'::regtype, 'tstzrange'::regtype) then
raise exception 'Function accepts only range types but got % type.', pg_typeof($1);
end if;
if array_length($2,1) is null then
return array[$1];
end if;
$0 := range_exclude($1,$2[array_lower($2,1)]);
for i in array_lower($2,1) + 1 .. array_upper($2,1) loop
select array(select x from (select unnest(range_exclude(x,$2[i])) from unnest($0) as t(x)) as t(x) where not isempty(x)) into $0;
end loop;
return $0;
end $$ immutable language plpgsql;
select range_exclude(numrange(8,17), array[numrange(10,11), numrange(13,20)]);
Tests:
select range_exclude(numrange(1,10), numrange(5,6));
select range_exclude(numrange(8,17), array[numrange(10,11), numrange(13,15)]);
Ergebnisse:
{"[1,5)","[6,10)"}
{"[8,10)","[11,13)","[15,17)"}
Und gleich für Zeitstempel:
select range_exclude(
tstzrange('2016-07-28 8:00','2016-07-28 17:00'),
array[
tstzrange('2016-07-28 10:00','2016-07-28 11:00'),
tstzrange('2016-07-28 13:00','2016-07-28 15:00')]);
Ergebnis:
{"[\"2016-07-28 08:00:00+03\",\"2016-07-28 10:00:00+03\")","[\"2016-07-28 11:00:00+03\",\"2016-07-28 13:00:00+03\")","[\"2016-07-28 15:00:00+03\",\"2016-07-28 17:00:00+03\")"}
[Bearbeiten] Ihre Frage ein und fügen Sie einige Beispieldaten und die erwartete Ausgabe auf der Grundlage dieser Daten. _Formatted_ Text bitte, [keine Screenshots] (http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-of-code-on-so-when-asking-a- Frage/285557 # 285557) –
Beide Antworten haben Beispiele, die ziemlich gut zu dem passen, was ich vorhatte, daher hilft es mir wahrscheinlich nicht, an dieser Stelle ein Beispiel hinzuzufügen. Aber ich schätze den Vorschlag und werde das bei zukünftigen Fragen tun. –