PHP MySQL(4.1)の質問です


テーブル名
school_date

フィールド
id
ken(東京都・神奈川県など)
area(新宿区・渋谷区など)
name(学校名)
他多数


このようなテーブルがあります。
そして実際にはこのようにデータが入っています。

1 東京都 新宿区 新宿高校・・・
2 東京都 渋谷区 渋谷高校・・・
3 東京都 新宿区 新宿御苑高校・・・
4 東京都 中央区 日本橋高校・・・
5 東京都 新宿区 歌舞伎町高校・・・
6 東京都 渋谷区 センター街高校・・・


----------
やりたい事
PHPで以下のようにHTML出力させたいです。


新宿区
 新宿高校
 新宿御苑高校
 歌舞伎町高校

渋谷区
 渋谷高校
 センター街高校

中央区
 日本橋高校


新宿区・渋谷区のようなareaの項目を1度だけ表示させるのが難しくてできません。
このように出力する事は可能でしょうか??
500ポイントほど用意致します。
よろしくお願いします。

回答の条件
  • 1人2回まで
  • 登録:2007/03/17 07:24:17
  • 終了:2007/03/19 10:18:53

ベストアンサー

id:nandedarou No.3

nandedarou回答回数230ベストアンサー獲得回数342007/03/17 15:17:35

ポイント300pt

テーブル名のschool_dateは、school_dataの書き間違いですか?

とりあえず、質問文のとおり、school_dateにしておきます。

テーブル名のschool_dateは、school_dataの書き間違いですか?
とりあえず、質問文のとおり、school_dateにしておきます。
>||
// 東京の全てのデータをとりだすSQL文。
// ※ORDER BYでarea順に並べて、同じareaのデータが連続するようにしておく
$ken = '東京都';
$sql = sprintf("SELECT * FROM school_date WHERE ken = '%s' ORDER BY area;", $ken);

// SQL文を実行し、連想配列として$dataに保存
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result)) {
   $data[] = $row;
}

// 表示処理
$printed_area = ''; // 初期化
foreach( $data as $key => $value ){
    
    // ※前に表示したareaと違ったら、areaを表示する。
    if($printed_area <> $value['area']){
        
      // 最初は、改行しないが、2個目以降のareaの前に改行する
        if($printed_area<>'') print "<br>";
        
        // areaを表示する
        print $value['area'].'<br>';
        
        // ※表示したareaは、printed_areaに保存する
        $printed_area = $value['area'];
        
    }
    
    // 学校名を表示する
    print '&nbsp;&nbsp;'.$value['name'].'<br>';
    
}

上記3つの※印の部分がポイントです。

いかがでしょうか?

その他の回答(2件)

id:Mook No.1

Mook回答回数1312ベストアンサー獲得回数3912007/03/17 09:20:02

ポイント200pt

やれないことはありませんが、必ずしも一回のクエリでやる必要はありません。

ときにはステップごとに処理をするほうが、問題を簡単にしてくれます。


いずれにせよクエリだけでは、ご希望のようにはできないので、PHP側の処理になるでしょう。

<?
// データベース情報
define( "db_Server", "localhost" );
define( "db_User", "foo" );
define( "db_Password", "bar" );
define( "db_Name", "testdb" );

// データベース接続
$conn = mysql_connect( db_Server, db_User, db_Password ) or die("接続エラー");
mysql_select_db(db_Name) or die("DATABASE 選択エラー     :".$dbName );

// エリアを表示
$sql = "SELECT DISTINCT ken, area FROM school_data ORDER BY ken;";
$res = mysql_query( $sql, $conn ) or die("エリアデータ抽出エラー<br>\n".$sql);
while ( $row = mysql_fetch_array( $res, MYSQL_ASSOC ) ) {
    print $row["area"]."<br>\n";
// エリア内の高校を表示
    $sql = "SELECT name FROM school_data WHERE area = '".$row["area"]."';";
    $sres = mysql_query( $sql, $conn ) or die("名前抽出エラー");
    while ( $srow = mysql_fetch_array( $sres, MYSQL_ASSOC ) ) {
        print "&nbsp;&nbsp;".$srow["name"]."<br>\n";
    }
    print "<br>\n";
}
mysql_close( $conn );
?>

一度のクエリで処理をしたければ、area順でデータを取得し、

area を見ながら変わったら表示をする、というような処理に

なると思います。

id:tobeoscontinue No.2

tobeoscontinue回答回数214ベストアンサー獲得回数542007/03/17 13:32:04

ポイント50pt

連想配列(keyが文字列)を使ってみました。

function array_nest($datas)
{
  foreach($datas as $data) {
    list($ken, $area, $name) = $data;
    $nest["$ken"]["$area"][] = $name;
  }
  return $nest;
}

二次元の配列を二次元の?連想配列に変換します。(名前はダメダメです。いいのが思いつかない)

この時点で東京や区名など同じもの(名前が同じ)は一つだけになります。

$res = array(
 array('東京都','新宿区','新宿高校'),
 array('東京都','渋谷区','渋谷高校'),
 array('東京都','新宿区','新宿御苑高校'),
 array('東京都','中央区','日本橋高校'),
 array('東京都','新宿区','歌舞伎町高校'),
 array('東京都','渋谷区','センター街高校')
);

サンプルとしてこのような二次元の配列を考えます。SQLの結果としても同じようなものを受け取ることは可能だと思います。

$nest = array_nest($res);
foreach ($nest as $ken => $a_ken) {
  echo $ken."<br>";
  foreach ($a_ken as $area => $a_area) {
    echo '&nbsp;'.$area."<br>";
    foreach ($a_area as $name) {
      echo '&nbsp;&nbsp;'.$name."<br>";
} } }

表示はちょっと長いです。

肝は

$nest["$ken"]["$area"][] = $name;

の部分で連想配列を使うことで重複する部分を判断することなく一つにできることです。

SQLの結果から直接$nestの連想配列を作った方がコードが短くなるとは思います。がコードの再利用などを考えると単純な構造を経由したほうが後々便利だとは思ます。

id:nandedarou No.3

nandedarou回答回数230ベストアンサー獲得回数342007/03/17 15:17:35ここでベストアンサー

ポイント300pt

テーブル名のschool_dateは、school_dataの書き間違いですか?

とりあえず、質問文のとおり、school_dateにしておきます。

テーブル名のschool_dateは、school_dataの書き間違いですか?
とりあえず、質問文のとおり、school_dateにしておきます。
>||
// 東京の全てのデータをとりだすSQL文。
// ※ORDER BYでarea順に並べて、同じareaのデータが連続するようにしておく
$ken = '東京都';
$sql = sprintf("SELECT * FROM school_date WHERE ken = '%s' ORDER BY area;", $ken);

// SQL文を実行し、連想配列として$dataに保存
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result)) {
   $data[] = $row;
}

// 表示処理
$printed_area = ''; // 初期化
foreach( $data as $key => $value ){
    
    // ※前に表示したareaと違ったら、areaを表示する。
    if($printed_area <> $value['area']){
        
      // 最初は、改行しないが、2個目以降のareaの前に改行する
        if($printed_area<>'') print "<br>";
        
        // areaを表示する
        print $value['area'].'<br>';
        
        // ※表示したareaは、printed_areaに保存する
        $printed_area = $value['area'];
        
    }
    
    // 学校名を表示する
    print '&nbsp;&nbsp;'.$value['name'].'<br>';
    
}

上記3つの※印の部分がポイントです。

いかがでしょうか?

  • id:Mook
    見直してみると、説明が不親切ですね。

    >新宿区・渋谷区のようなareaの項目を1度だけ表示させるの
    のは、通常SQL では DISTINCT 句を使用します。

    これにより重複せずに結果が表示されます。
  • id:tokyosmash
    テーブル名間違っていましたね。
    school_dateではなくschool_dataです。
    混乱させてしまってすみません。
    今からみなさんの方法を試してみます。
  • id:Mook
    コードに誤記がありました。
    動作には影響ないとは思いますが、データベースのテーブル選択に失敗した場合、
     mysql_select_db(db_Name) or die("DATABASE 選択エラー :".$dbName );
    の $dbName は使用していませんでしたので、db_Name に変更してください。

    お手数をおかけします。
  • id:tokyosmash
    おかげさまで思い通りの動きをしてくれています。
    これは非常に便利なスクリプト?が出来ました。
    今までMovableTypeに頼っていた部分をPHPとMySQLで出来るようになったので、なんだか嬉しいです。

    3つの回答を頂いたので、自分なりにわかりやすいところを混ぜこぜにして作りました。みなさんどうもありがとうございます。

    SQLの書き方が難しいですね。ちょっとづつ自分でも書けるようになってきましたけど。。

    今後ともtokyosmashを見つけたらよろしくお願いします。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません