useful function & operator & custom operator for Row and Array Comparisons

Postgres2015全國用戶大會將於11月20至21日在北京麗亭華苑酒店召開。本次大會嘉賓陣容強大,國內頂級PostgreSQL數據庫專家將悉數到場,並特邀歐洲、俄羅斯、日本、美國等國家和地區的數據庫方面專家助陣:

  • Postgres-XC項目的發起人鈴木市一(SUZUKI Koichi)
  • Postgres-XL的項目發起人Mason Sharp
  • pgpool的作者石井達夫(Tatsuo Ishii)
  • PG-Strom的作者海外浩平(Kaigai Kohei)
  • Greenplum研發總監姚延棟
  • 周正中(德哥), PostgreSQL中國用戶會創始人之一
  • 汪洋,平安科技數據庫技術部經理
  • ……
 
2015年度PG大象會報名地址:http://postgres2015.eventdove.com/PostgreSQL中國社區: http://postgres.cn/PostgreSQL專業1羣: 3336901(已滿)PostgreSQL專業2羣: 100910388PostgreSQL專業3羣: 150657323


社區裏一位同學的需求:
請問   有什麼辦法可以判斷 ,一個數組裏面至少一個元素在一個範圍之間?

select 1 <= any(ARRAY[0.8,3.2]) and 3 >= any(ARRAY[0.8,3.2])

例如,這個,我喜歡的結果是f

我們注意一下,這個SQL實際上返回的是TRUE,因爲分開來看1 <= any(ARRAY[0.8,3.2])返回的是true, 3 >= any(ARRAY[0.8,3.2])返回的也是ture, 所以這個SQL返回的意思TRUE。

postgres=# select 1 <= any(ARRAY[0.8,3.2]) and 3 >= any(ARRAY[0.8,3.2]);
 ?column? 
----------
 t
(1 row)

所以這個SQL不能滿足用戶的需求,而需要使用這個數組中的每個對象和1,3對比,然後再使用bool_or聚合結果。
例如:

postgres=# select 1 <= i and 3>=i from unnest(ARRAY[0.8,3.2]) t(i);
 ?column? 
----------
 f
 f
(2 rows)
postgres=# select bool_or(1 <= i and 3>=i) from unnest(ARRAY[0.8,3.2]) t(i);
 bool_or 
---------
 f
(1 row)


當然還有更好的方法,那就是用範圍類型和ANY構造。

postgres=# select '[1,3]'::numrange @> any(array[0.8,3.1]);
 ?column? 
----------
 f
(1 row)


如果你的系統不支持範圍類型,則可以自定義一個函數來實現它,輸入爲數組以及兩個數字,返回值爲布爾邏輯值。

postgres=# create or replace function f_cmp(a _numeric,b numeric,c numeric) returns boolean as $$
declare 
  res boolean := false; 
  i numeric;
begin
  FOREACH i in ARRAY a LOOP
    res := (i between b and c) or (i between c and b) or res; 
  END LOOP;
  return res;
end;
$$ language plpgsql strict;
CREATE FUNCTION

postgres=# select f_cmp(array[0.8,3.1],1,3);
 f_cmp 
-------
 f
(1 row)


我之前寫過一個類似的例子, 模糊匹配數組中的元素。

[參考]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章