0

codeigniter アクティブ レコードを使用して PHP でこのような結果セットを達成する最も効率的な方法は何ですか?

[2] => stdClass Object
    (
        [id] => 12
        [title] => 2 sections
        [layout_id] => 1
        [layout] => stdClass Object
            (
                [id] => 1
                [file] => 3_column.php
                [title] => 3 Column
            )

        [sections] => Array
            (
                [0] => stdClass Object
                    (
                        [module_id] => 12
                        [section_id] => 1
                    )

                [1] => stdClass Object
                    (
                        [module_id] => 12
                        [section_id] => 2
                    )

            )

    )   

これは私に望ましいネストされた結果を与えるものですが、このアプローチにはいくつかの大きな非効率性があります(select *for each クエリを無視してください)

public function all()
{
  $rows = $this->db->get('modules')->result();

  foreach($rows as &$row)
  {
    $row->layout = $this->db->get_where('layouts', array('id' => $row->layout_id), 1)->first_row();
    $row->sections = $this->db->get_where('modules_sections', array('module_id' => $row->id))->result();
  }

  return $rows;
}
4

2 に答える 2

1

いくつかの結合と GROUP_BY 句を使用して、これらのいくつかのクエリを 1 つのクエリに簡単に変換できます。このアプローチの最大の欠点は、データのグループ化と区切りが少し必要になることですが、PHP は区切られたデータの「爆発」に優れています。これを試してください:

function all()
{

    $this->db->select("`modules`.*, CONCAT(`layouts`.`id`,'".DATA_SUBDELIMITER."',`layouts`.`title`,'".DATA_SUBDELIMITER."',`layouts`.`file`) AS layout, CAST(GROUP_CONCAT(`sections`.`id`,'".DATA_SUBDELIMITER."',`sections`.`title` SEPARATOR '".DATA_DELIMITER."') AS CHAR) AS sections", false);
    $this->db->from('modules');
    $this->db->join('layouts', 'layouts.id = modules.layout_id');
    $this->db->join('modules_sections', 'modules_sections.module_id = modules.id');
    $this->db->join('sections', 'sections.id = modules_sections.section_id');
    $this->db->group_by('modules.id');

    $rows = $this->db->get()->result_array();
    foreach($rows as &$row)
    {
        foreach($row as $k=>&$r)
        {
            if($k=='layout' || $k=='sections')
            {
                $new_r = explode(DATA_DELIMITER, $r);
                foreach($new_r as &$c)
                {
                    $e = explode(DATA_SUBDELIMITER,$c);
                    $c = array();
                    list($c['id'],$c['title']) = $e;
                    if(!empty($e[2])) $c['file'] = $e[2];
                }
                if($k=='layout') $new_r = $new_r[0];
                $r = $new_r;
            }
        }
    }

    return $rows;
}

この例では、データを区切る文字に DATA_DELIMITER と DATA_SUBDELIMITER を使用しています。これらの定数を使用する場合は、おそらく application/config/constants.php ファイルで定義する必要があります。おそらく次のようになります。

define('DATA_DELIMITER','||');
define('DATA_SUBDELIMITER','##');

このコードをテストすると、次のような結果が得られました。

Array
(
    [0] => Array
        (
            [id] => 1
            [title] => Module 1
            [layout_id] => 1
            [layout] => Array
                (
                    [title] => 3 Column
                    [id] => 1
                    [file] => 3_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 1
                            [id] => 1
                        )

                    [1] => Array
                        (
                            [title] => Section 2
                            [id] => 2
                        )

                )

        )

    [1] => Array
        (
            [id] => 2
            [title] => Module 2
            [layout_id] => 2
            [layout] => Array
                (
                    [title] => 2 Column
                    [id] => 2
                    [file] => 2_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 1
                            [id] => 1
                        )

                    [1] => Array
                        (
                            [title] => Section 3
                            [id] => 3
                        )

                )

        )

    [2] => Array
        (
            [id] => 3
            [title] => Module 3
            [layout_id] => 1
            [layout] => Array
                (
                    [title] => 3 Column
                    [id] => 1
                    [file] => 3_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 3
                            [id] => 3
                        )

                )

        )

    [3] => Array
        (
            [id] => 4
            [title] => Module 4
            [layout_id] => 2
            [layout] => Array
                (
                    [title] => 2 Column
                    [id] => 2
                    [file] => 2_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 1
                            [id] => 1
                        )

                    [1] => Array
                        (
                            [title] => Section 2
                            [id] => 2
                        )

                    [2] => Array
                        (
                            [title] => Section 3
                            [id] => 3
                        )

                    [3] => Array
                        (
                            [title] => Section 4
                            [id] => 4
                        )

                )

        )

)
于 2012-08-02T21:55:23.037 に答える
0

ここでの効率とは、一種の相対的な用語です。

SQLサーバーでクエリを最小限に抑えることを検討している場合は、いつでもオブジェクトをシリアル化してキャッシュテーブルに格納できます。ルックアップは1回だけですが、あらゆる種類の書き込み操作でこれらのオブジェクトを維持する必要があります。それ以外は、おそらく負荷テストを行って、ボトルネックがどこにあるかを確認する必要があります。複数のクエリは、巨大なマルチテーブル結合よりも高速な場合があります。

于 2012-08-02T21:26:56.593 に答える