人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

MYSQL(5.0)のソートについて質問です。

次のようなデータがあります。

日付, 店舗, 面積
1, A0/C0/E1, 50
2, B0, 40
3, E1, 20
4, B1, 20
5, C1/C2, 10
6, B2, 20
7, D3, 30

A0/C0/E1はA0,C0,E1の合計を表します。
また、0は当該店舗全てを、1、2はその一部分を表します(C1やC2は、C0の一部)。

これを次のように並べ替えたいと思います。
日付, 店舗, 面積
1, A0/C0/E1, 50
5, C1/C2, 10
3, E1, 20
2, B0, 40
4, B1, 20
6, B2, 20
7, D3, 30

並べ替えの順序としては、
1.もっとも大きい店舗の集合(例では A0/C0/E1)をはじめに置く。
2.つぎに1に含まれる下位の集合(例では C1/C2, E1)があればそれらを並べる。
3.上記に含まれない店舗の集合を大きい順に並べる(例ではB0, B1, B2)。

上記のように並べ替える方法がありましたら教えてください。
よろしくお願いいたします。

補足:
A0/C0/E1 と A0/B1/C1というように一部分が重なるようなデータはありません(完全に含むか、全く含まないデータしかありません)。

●質問者: gillsderais
●カテゴリ:ビジネス・経営 コンピュータ
✍キーワード:b2 D3 MySQL ソート データ
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● kn1967
●48ポイント

動作確認していないのですがいかがでしょう?

SELECT T3.*
FROM (SELECT *
 ,FIND_IN_SET("/",REPLACE(店舗,"/",",")) AS 店舗数
 ,IF((SELECT COUNT(*) FROM テーブル名 AS T2 WHERE INSTR(T2.店舗,"/")=0 AND INSTR(T1.店舗,T2.店舗)>0)>0,1,0) AS 下位
 FROM テーブル名 AS T1
) AS T3
ORDER BY T3.店舗数 DESC,T3.下位 DESC,T3.面積 DESC;

店舗数や下位が何を表しているかを示すため全てのフィールドを返していますが

結果セットとして日付,店舗,面積だけでよろしければ一行目を

SELECT T3.*

から

SELECT T3.日付,T3.店舗,T3.面積

に変えてください。

◎質問者からの返答

ありがとうございます。

ただ、うまく動きません。

結果として得られるのはこんな感じです。

日付, 店舗, 面積, 店舗数,下位

1, A0/C0/E1, 50, 0, 1

2, B0, 40, 0, 1

7, D3, 30, 0, 1

3, E1, 20, 0, 1

4, B1, 20, 0, 1

6, B2, 20, 0, 1

5, C1/C2, 10, 0, 0

なんかすごくおしいような気がしますが、

当方初心者なため、ご提示いただいたSQLを十分理解できず、

誤りの箇所が見つけられません。

ひきつづき、ご回答のほどよろしくお願いいたします。

(可能であれば、どのような操作を行ったのか説明していただけると助かります)


2 ● kn1967
●48ポイント

あいもかわらずテスト環境が使えず、脳内だけで申し訳ありませんが・・・。


店舗数が全てゼロになる点は下記のように書き直してくださいませ。

,FIND_IN_SET('/',REPLACE(T1.店舗,'/',',/,')) AS 店舗数

この式の意味はFIND_IN_SETがカンマで区切られた複数の文字列の中から特定の文字列の個数を探します。

その前段階としてREPLACEでカンマをいれてあります。

A0/C0/E1 → A0,/,C0,/,E1 → /は2
C1/C2 → C1,/,C2 → /は1
E1 → E1 → /はゼロ

これらは区切りの数を数えているだけなので、実際の店舗数を求めるためには全て+1が必要なのだけれど

1.もっとも大きい店舗の集合(例では A0/C0/E1)をはじめに置く。

という並び順として使えれば良いので省きました。


下位の計算がおかしい点は下記のように書き直してくださいませ。

,IF((SELECT COUNT(*) FROM テーブル名 AS T2 WHERE INSTR(T1.店舗,'/')=0 AND INSTR(T2.店舗,T1.店舗)>0)>0,1,0) AS 下位

店舗に / が含まれず、かつ、他のレコード内に含まれれば下位には1が入る。

複数店舗の合計の場合と、どこにも属さない場合にはゼロが入る

こちらは

2.つぎに1に含まれる下位の集合(例では C1/C2, E1)があればそれらを並べる。

を満たすためだけに使う


SELECT T3.*
FROM (SELECT *
 ,FIND_IN_SET('/',REPLACE(T1.店舗,'/',',/,')) AS 店舗数
 ,IF((SELECT COUNT(*) FROM テーブル名 AS T2 WHERE INSTR(T1.店舗,'/')=0 AND INSTR(T2.店舗,T1.店舗)>0)>0,1,0) AS 下位
 FROM テーブル名 AS T1
) AS T3
ORDER BY T3.店舗数 DESC,T3.下位 DESC,T3.面積 DESC;
◎質問者からの返答

1.Find_in_setですが、引数と一致する値の文字列の位置を返すので、「/」が含まれる場合は、全て「2」を返してしまいます。

また、「ORDER BY T3.店舗数」となっているので、複数店舗の集合が上位に来てしまいます(たとえば「B1/D2/F0」があった場合、「A0/C0/E1」に含まれないのにその直下に来てしまいます)。

2.「他のレコード内に含まれれば下位には1」とありますが、すべてそれ自身に含まれてしまうので1になってしまいませんか?

結果的に、

日付, 店舗, 面積, 店舗数,下位

1, A0/C0/E1, 50, 2, 0

5, C1/C2, 10, 2, 0

2, B0, 40, 0, 1

7, D3, 30, 0, 1

3, E1, 20, 0, 1

4, B1, 20, 0, 1

6, B2, 20, 0, 1

こんな感じになりました。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ