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

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
于 2012-08-29T06:08:12.433 に答える
3

これが1つの方法です。単一の列から2つの場所を分離し、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

あなたはもっと知的なものを探しているかもしれませんか?「場所」というのは「from-to」のようなものだと思いますか? locationまた、このように列に複数の値を格納するという決定にも疑問があります。location1location2を別々の列として保存する方がはるかに良いでしょう。

于 2012-08-29T05:57:46.730 に答える
0

現在受け入れられている回答は後で問題を引き起こすように思われるため、別の選択肢があります。これは、lc によるソリューションに大きく基づいています。しかし、注文を処理します。

まず、SQL テーブルには行の順序が明確に定義されていません。テーブルのすべての行をクエリすると、それらの行は特定の順序で返されますが、その順序は定義されておらず、行が追加された順序に関連している場合も関連していない場合もあり、予期せず変更される場合もあります。したがって、特定の順序で行を処理する場合は、列を追加して、ある種のシーケンス番号または類似のものを含める必要があります。それが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

ユニオンはさまざまな場所のリストを生成し、最も外側の選択を使用して単一の文字列に結合されます。ユニオンの最初の部分は、ルートの最初の部分の前半を生成しますが、ユニオンの 2 番目の部分は、すべての部分の後半を提供します。ユニオンの結果の順序はまだ定義されていないため、全体的な順序付け規則が必要です。limit 句を使用してルートの最初の部分を実際に選択できるように、前半の順序付けルールも必要です。

これは、 Omeshがセットアップしたものに基づく sqlfiddle です。列がないためseq、列を使用して順序付けを行いicodeます。したがって、結果は期待したものとは異なり、Manila - Bohol - Cebu - Manila代わりに生成されます。

列を追加する場合はseq、データベース スキーマを変更する必要があるため、各部分の 2 つのエンドポイントが 2 つの異なる列になるように変更することもできます。を使用して列を結合するのCONCATは簡単ですが、それらを分割すると、開発者とデータベース エンジンの両方にとってクエリが複雑になります。

データベース スキーマを制御できないためにシーケンス列を追加できない場合は、問題が発生します。ここでのコメントは、常にサイクルを探していることを示していますが、順序付けられていないデータからそのようなサイクルを見つけるには、SQL レベルではすぐに利用できないmapを使用して行うのが最適です。必要に応じてストアド プロシージャを使用して、ジャーニーの各部分に対して 1 つの select を実行することでこれを実現できますが、私があなたなら、アプリケーション レベルでこれに取り組みたいと思います。

于 2012-09-05T09:05:24.860 に答える