2013-10-07 79 views
8

我想找到一個優雅的方式來模擬Postgres中MySQL的subtring_index()函數的行爲。在PGSQL中模擬MySQL的substring_index()

在MySQL中,它是那麼容易,因爲:

mysql> create temporary table test1(test varchar(200)); 
Query OK, 0 rows affected (0.01 sec) 

mysql> insert into test1 values('apples||oranges'),('apples||grapes'); 
Query OK, 2 rows affected (0.00 sec) 
Records: 2 Duplicates: 0 Warnings: 0 

mysql> select * from test1; 
+-----------------+ 
| test   | 
+-----------------+ 
| apples||oranges | 
| apples||grapes | 
+-----------------+ 
2 rows in set (0.00 sec) 

mysql> select substring_index(test, '||', 1) as field1, substring_index(test, '||', -1) as field2 from test1; 
+--------+---------+ 
| field1 | field2 | 
+--------+---------+ 
| apples | oranges | 
| apples | grapes | 
+--------+---------+ 
2 rows in set (0.00 sec) 

但PGSQL我目前的解決辦法是相當難看:

hoth=# create temporary table test1(test text); 
CREATE TABLE 

hoth=# insert into test1 values('apples||oranges'),('apples||grapes'); 
INSERT 0 2 

hoth=# select * from test1; 
     test  
----------------- 
apples||oranges 
apples||grapes 
(2 rows) 

hoth=# select substring(test, 0, position('||' in test)) as field1, substring(test, position('||' in test) + 2, char_length(test)) as field2 from test1; 
field1 | field2 
--------+--------- 
apples | oranges 
apples | grapes 
(2 rows) 

或許有使用正則表達式一個更優雅的解決方案,或者可能即使通過將字符串拆分爲變量中的數組,可能會減少開銷,如果字符串是從子查詢或其他東西派生的,我歡迎任何建議。

+2

我想外面的現成解決方案是保存的方式,是更適合您要執行的查詢,您的數據(例如,通過標準化,或使用數組類型)。我意識到這並不總是一種選擇,但我認爲我會把它拋出去,特別是因爲你的MySQL例子看起來被專門編碼爲分成兩部分。 – IMSoP

回答

10

總是花時間瀏覽手冊。

http://www.postgresql.org/docs/current/static/functions-string.html

如果split_part(string text, delimiter text, field int)不會做你想做的(多了,如果我理解你的MySQL功能),那麼你就需要解釋的位置和原因。

+1

啊,手冊似乎將「字符串函數和操作符」與「其他字符串函數」分開,後者顯然是我忽略的。謝謝。 –

+0

@jesse_galley:[「其中一些內部用於實現表9-5中列出的** SQL標準**字符串函數。」](http://www.postgresql.org/docs/current/static/ functions-string.html)[強調我的]。所以第一個列表是爲了覆蓋SQL標準指定的功能,而第二個列表是爲了覆蓋PostgreSQL擴展。 –

+1

儘管SPLIT_PART解決了上述示例,但它不是模擬MySQL的SUBSTRING_INDEX的工具,因爲SUBSTRING_INDEX將子字符串返回到指定數量的分隔符的左側或右側。如何面對任意數量的分隔符時模擬它的行爲?例如,從URL的大部分中選擇域;例如:從'sports.adventures.hobbies.domain.com'和'pets.domain.com'中選擇'domain.com'?爲了解決PostgreSQL中的這個問題,我們可能需要reg表達式或組合各種字符串函數。 –

1

這是我如何在PostgreSQL的

CREATE OR REPLACE FUNCTION public.substring_index (
    str text, 
    delim text, 
    count integer = 1, 
    out substring_index text 
) 
RETURNS text AS 
$body$ 
BEGIN 
    IF count > 0 THEN 
    substring_index = array_to_string((string_to_array(str, delim))[:count], delim); 
    ELSE 
    DECLARE 
     _array TEXT[]; 
    BEGIN 
     _array = string_to_array(str, delim); 
     substring_index = array_to_string(_array[array_length(_array, 1) + count + 1:], delim);  
    END; 
    END IF; 
END; 
$body$ 
LANGUAGE 'plpgsql' 
IMMUTABLE 
CALLED ON NULL INPUT 
SECURITY INVOKER 
COST 5; 

實施(或模擬)MySQL的subtring_index(),這裏是從MySQL的文檔的例子;

postgres=# SELECT substring_index('www.mysql.com', '.', 2); 
substring_index 
----------------- 
www.mysql 
(1 row) 

postgres=# SELECT substring_index('www.mysql.com', '.', -2); 
substring_index 
----------------- 
mysql.com 
(1 row)