MySQL字符串函数

时间:2012-08-29 05:46:03

标签: mysql string function

我有一张包含以下数据的表格:

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字符串函数并不熟悉,所以我需要一些关于如何使其工作的想法。任何帮助将不胜感激。非常感谢!

3 个答案:

答案 0 :(得分:6)

您需要在SEPARATOR函数中使用GROUP_CONCAT

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

答案 1 :(得分:3)

这是一种方式。它将您的单个location列中的两个位置分开,区分它,然后将它重新组合在一起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存储为单独的列会更好。

答案 2 :(得分:0)

以后the currently accepted answer似乎cause problems,这是另一种选择。它主要基于the solution by lc.,但负责订购。

首先:SQL表没有明确定义的行顺序。当您查询表的所有行时,这些行将按特定顺序返回,但该顺序未定义,可能与添加行的顺序相关,也可能不相关,并且可能会意外更改。因此,当您要按给定顺序处理行时,应添加一列以包含某种序列号或smilar。这就是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来完成,{{3}}在SQL级别不可用。你可以通过存储过程实现这一点,如果必须,为jurney的每个部分执行一个选择,但如果我是你,我宁愿在应用程序级别解决这个问题。