2012-08-29 82 views
8

我有下列數據的表:MySQL的字符串函數

reservno || icode || location 
00004 || 00021 || Bohol - Cebu 
00004 || 00022 || Cebu - Manila 
00004 || 00014 || Manila - Bohol 

我用這個查詢檢索位置的連結值。

SELECT GROUP_CONCAT(location) from location_list where reservno='00004'; 

查詢結果看起來是這樣的:

GROUP_CONCAT(location) 
Bohol - Cebu,Cebu - Manila,Manila - Bohol 

但我想要做的是查詢看起來像這樣:Bohol - Cebu - Manila - Bohol。我想合併這樣的結果。我怎樣才能做到這一點?我對MySQL字符串函數並不熟悉,所以我需要一些關於如何使其工作的想法。任何幫助將不勝感激。非常感謝!

+2

你如何確定記錄的連接順序? – eggyal

回答

6

您需要GROUP_CONCAT功能使用SEPARATOR

SELECT GROUP_CONCAT(IF((@var_ctr := @var_ctr + 1) = @cnt, 
         location, 
         SUBSTRING_INDEX(location,' - ', 1) 
         ) 
         ORDER BY loc_id ASC 
         SEPARATOR ' - ') AS locations 

FROM location_list, 
    (SELECT @cnt := COUNT(1), @var_ctr := 0 
     FROM location_list 
     WHERE reservno='00004' 
    ) dummy 
WHERE reservno='00004'; 

例子:SQLFIDDLE

這不是存儲在同一列多個值的好做法,更好的方法可能是:

reservno || icode || location_from || location_to 
00004 || 00021 || Bohol   || Cebu 
00004 || 00022 || Cebu   || Manila 
00004 || 00014 || Manila  || Bohol 
+0

哇!這只是一種魔法!非常感謝! :)))) – xjshiya

+0

不客氣!乾杯! :) – Omesh

+2

@xjshiya這不能保證這將按照你想要的順序出現。你應該確保你指定了'order by'子句。 –

3

這是一種方法。它從單一location列兩個位置分離出來,distincts它,然後把它重新走到一起SQL Fiddle

SELECT GROUP_CONCAT(DISTINCT loc SEPARATOR ' - ') 
FROM 
(
    SELECT SUBSTRING_INDEX(location, ' - ', 1) AS loc 
    FROM location_list 
    WHERE reservno='00004' 
    UNION ALL 
    SELECT SUBSTRING_INDEX(location, ' - ', -1) AS loc 
    FROM location_list 
    WHERE reservno='00004' 
) separatedLocs 

你可能會尋找一些更智能的關係嗎?我感覺「位置」更像是一種「從 - 到」的東西?我也質疑在您的location列中存儲多個值的決定。將location1location2作爲單獨的列存儲會更好。

+0

它恢復:保和 - 宿務 - 馬尼拉。還有什麼辦法可以在最後部分添加保和?像這樣:保和島 - 宿霧 - 馬尼拉 - 保和省?感謝你的回答! – xjshiya

+0

@xjshiya你如何確定他們應該加入的順序呢? –

+0

你是什麼意思? – xjshiya

0

由於the currently accepted answer後來似乎cause problems,這裏是另一種選擇。它主要基於the solution by lc.,但需要照顧訂購。

首先:SQL表有沒有明確定義的行順序。當查詢表的所有行時,這些行將以特定順序返回,但該順序未定義,可能與行添加的順序相關,也可能不相關,並且可能會意外更改。所以當你想以給定的順序處理你的行時,你應該添加一個列來包含某種序列號或者相似的。這就是爲什麼lc。 kept bugging you關於位置的順序。

如果你有這樣一個專欄,叫seq,那麼你可以使用下面的查詢:

SELECT GROUP_CONCAT(loc SEPARATOR ' - ') 
FROM (
(SELECT 1 half, seq, SUBSTRING_INDEX(location, ' - ', 1) loc 
    FROM location_list 
    WHERE reservno='00004' 
    ORDER BY seq 
    LIMIT 1) 
UNION ALL 
(SELECT 2 half, seq, SUBSTRING_INDEX(location, ' - ', -1) loc 
    FROM location_list 
    WHERE reservno='00004') 
ORDER BY half, seq 
) locs 

聯盟將產生的各種位置的列表,這是使用最外層的合併成一個單一字符串選擇。工會的第一部分產生路線第一部分的前半部分,而工會的第二部分將給你所有部分的後半部分。迄今爲止,聯合結果的順序尚未定義,所以我們需要一個整體排序規則。我們還需要一個上半年的訂購規則,以便我們真正選擇具有限制條款的路線的第一部分。

Here是基於一個Omesh設置的sqlfiddle。缺少seq列,它使用icode列來排序。因此,結果與您預期的結果不同,並生成Manila - Bohol - Cebu - Manila

如果添加seq列,那麼您必須更改數據庫模式,因此您可能需要更改數據庫模式,以便將每個部分的兩個端點轉換爲兩個不同的列。使用CONCAT組合列很簡單,但將它們拆分會增加開發人員和數據庫引擎的查詢複雜性。

如果您無法添加序列列,因爲您無法控制數據庫模式,那麼您遇到了麻煩。 Your comment here表示您一直在尋找一個循環,但從無序數據中找到這樣一個循環最好使用map來完成,而這在SQL級別上並不容易得到。如果必須的話,你可以通過存儲過程來實現這一點,爲jurney的每個部分執行一次select,但是如果我是你,我寧願在應用程序級別處理這個問題。