8

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

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

4

3 回答 3

6

您需要SEPARATORGROUP_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
于 2012-08-29T06:08:12.433 回答
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我也质疑像这样在您的列中存储多个值的决定。location1将 a和location2作为单独的列存储会更好。

于 2012-08-29T05:57:46.730 回答
0

由于当前接受的答案似乎稍后会引起问题,因此这是另一种选择。它在很大程度上基于lc 的解决方案。但负责订购。

首先:SQL 表没有明确定义的行顺序。当您查询表的所有行时,这些行将按特定顺序返回,但该顺序未定义,可能与添加行的顺序相关,也可能不相关,并且可能会意外更改。因此,当您想按给定顺序处理行时,您应该添加一列以包含某种序列号或 smilar。这就是为什么 lc. 一直在烦你关于位置的顺序。

如果您有这样的列,称为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

联合将产生一个不同位置的列表,使用最外层的选择将其组合成一个字符串。联合的第一部分产生路线第一部分的前半部分,而联合的第二部分将为您提供所有部分的后半部分。到目前为止联合结果的顺序是未定义的,所以我们需要一个整体的排序规则。我们还需要前半部分的排序规则,以便我们真正选择带有限制子句的路线的前半部分。

是一个基于 Omesh 设置的 sqlfiddle。由于缺少seq列,它使用icode列来排序。因此,结果与您预期的不同,Manila - Bohol - Cebu - Manila而是产生了。

如果添加seq列,则必须更改数据库模式,因此您不妨更改它,使每个部分的两个端点变成两个不同的列。使用组合列CONCAT很简单,但是拆分它们会增加开发人员和数据库引擎的查询的复杂性。

如果您无法添加序列列,因为您无法控制数据库模式,那么您就有麻烦了。您在这里的评论表明您一直在寻找一个循环,但是从无序数据中找到这样一个循环最好使用map来完成,这在 SQL 级别并不容易获得。如果必须,您可以通过存储过程来实现这一点,为陪审团的每个部分执行一个选择,但如果我是你,我宁愿在应用程序级别解决这个问题。

于 2012-09-05T09:05:24.860 回答