PostgreSQL:范围差异的结果不会是连续的

gue*_*tli 5 postgresql range-types

如何从较大的范围中减去较小的子范围?

123456789
    567
Run Code Online (Sandbox Code Playgroud)

结果:

1234   89
Run Code Online (Sandbox Code Playgroud)

查询语句:

select '[1,9]'::int4range - '[5,7]'::int4range;
ERROR:  result of range difference would not be contiguous
Run Code Online (Sandbox Code Playgroud)

结果不适合 int4range,因为它不连续。

如何将结果作为一组 int4ranges?

dez*_*zso 3

解决方案可能是这样的

\n\n
CREATE TABLE test_ranges (\n    big_range int4range,\n    small_range int4range,\n    test_case text\n);\n\nINSERT INTO test_ranges\nVALUES \n  (\'[1,9]\'::int4range, \'[5,7]\'::int4range, \'smaller range splits bigger into two\'),\n  (\'[1,9]\'::int4range, \'[1,9]\'::int4range, \'smaller is the same as bigger\'),\n  (\'[1,9]\'::int4range, \'[0,9]\'::int4range, \'smaller is bigger\'),\n  (\'[1,9]\'::int4range, \'[1,4]\'::int4range, \'smaller removes the left part of bigger (same effect expected on the right side)\'),\n  (\'[1,9]\'::int4range, \'empty\'::int4range, \'smaller is empty\'),\n  (\'empty\'::int4range, \'[5,7]\'::int4range, \'bigger is empty\');\n\n/* please note that you have to reorganize the query a bit \n   in order to get the \'halves\' as a set */\n\nSELECT \n    CASE WHEN isempty(small_range)\n         THEN big_range\n         ELSE big_range - int4range(lower(small_range), upper(big_range)) \n    END AS first_half,\n    big_range - int4range(lower(big_range), upper(small_range)) AS second_half, \n    test_case\nFROM test_ranges;\n
Run Code Online (Sandbox Code Playgroud)\n\n

注意

\n\n
test=# SELECT \'[1,5)\'::int4range = \'[1,4]\'::int4range;\n ?column? \n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n t\n
Run Code Online (Sandbox Code Playgroud)\n\n

有一个小的SQLFiddle可以在工作中展示这一点。感谢 ypercube 让我注意到原始查询未涵盖的一个极端情况。

\n