バージョン: v2.3.0
select
テーブルからデータを取得します。
select($table, $columns)
table [string]
対象のテーブル名。
columns [array/string]
取得するカラム。
select($table, $columns, $where)
table [string]
対象のテーブル名。
columns [array/string]
取得するカラム。
where [array] (省略可)
結果を絞り込むための WHERE 条件。
select($table, $join, $columns, $where)
table [string]
対象のテーブル名。
join [array]
関連テーブルを結合するための JOIN 定義。JOIN が不要な場合は省略できます。
columns [array/string]
取得するカラム。
where [array] (省略可)
結果を絞り込むための WHERE 条件。
戻り値
[array] 取得結果の配列。
* を columns パラメータに指定するとすべてのカラムを取得できますが、パフォーマンスと可読性の観点から、必要なカラムだけを明示的に指定することをおすすめします。$data = $database->select("account", [
"user_name",
"email"
], [
"user_id[>]" => 100
]);
// 結果例:
// array(
// [0] => array(
// "user_name" => "foo",
// "email" => "foo@bar.com"
// ),
// [1] => array(
// "user_name" => "cat",
// "email" => "cat@dog.com"
// )
// )
foreach ($data as $item) {
echo "ユーザー: " . $item["user_name"] . " - メール: " . $item["email"] . "<br/>";
}
// すべての列を選択します。
$data = $database->select("account", "*");
// 1 列だけを選択します。
$data = $database->select("account", "user_name");
// 結果例:
// array(
// [0] => "foo",
// [1] => "cat"
// )
コールバックで結果を逐次処理する
デフォルトでは、
select() は結果セット全体をメモリに読み込み、配列として返します。大量の行を取得する場合、メモリ使用量が大きく増えることがあります。
function ($data) {} のようなコールバックを select() の最後の引数に渡すと、Medoo は結果セット全体をメモリに保持せず、各行を順にフェッチしてその場で処理します。この方法は、大量データを扱うときに特にメモリ効率に優れています。
$database->select("account", ["name"], function ($data) {
echo $data["name"];
});
$database->select("account", [
"name"
], function ($data) {
echo $data["name"];
});
メモリ使用量の比較
次の例では、MySQL データベースから 1,000、5,000、および 20,000 行をフェッチして出力するときのメモリ使用量を比較します。メモリ使用量は
memory_get_usage() で測定されます。// 方法 1
$database->select("account", ["name"], function ($data) {
echo $data["name"];
});
// 比較対象:
// 方法 2
$data = $database->select("account", ["name"]);
foreach ($data as $item) {
echo $item["name"];
}
| 方法 1 | 方法 2 | |
| 1,000 レコード | 789 KB | 1.2 MB |
| 5,000 レコード | 1.1 MB | 3.3 MB |
| 20,000 レコード | 2.26 MB | 11.1 MB |
テーブル結合(JOIN)
SQL の JOIN 句は、複数のテーブルの行を結合します。Medoo は、こうした結合を組み立てるためのシンプルな構文を提供します。
- [>] ==> LEFT JOIN
- [<] ==> RIGHT JOIN
- [<>] ==> FULL JOIN
- [><] ==> INNER JOIN
$database->select("post", [
// メインテーブルと結合先テーブルの関連を定義します。
"[>]account" => ["author_id" => "user_id"]
], [
"post.title",
"account.city"
]);
post テーブルのカラム author_id は、account テーブルのカラム user_id に対応します。"[>]account" => ["author_id" => "user_id"]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"
両方のテーブルで同じカラム名が使われている場合は、省略形を使用できます。
"[>]album" => "user_id"
LEFT JOIN "album" USING ("user_id")
両方のテーブルで複数のカラム名が共通している場合は、それらを配列として渡せます。
"[>]photo" => ["user_id", "avatar_id"]
LEFT JOIN "photo" USING ("user_id", "avatar_id")
同じテーブルを複数回結合する必要がある場合は、結合されたテーブルに別名を割り当てます。
"[>]account (replier)" => ["replier_id" => "user_id"]
LEFT JOIN "account" AS "replier" ON "post"."replier_id" = "replier"."user_id"
カラム名の前にテーブル名を付けることで、先に結合したテーブルを参照することもできます。
"[>]account" => ["author_id" => "user_id"], "[>]album" => ["account.user_id" => "user_id"]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id" LEFT JOIN "album" ON "account"."user_id" = "album"."user_id"
複数の JOIN 条件
"[>]account" => [ "author_id" => "user_id", "album.user_id" => "user_id" ]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id" AND "album"."user_id" = "account"."user_id"
追加の JOIN 条件
結合句に論理条件を追加することもできます。
"[>]comment" => [ "author_id" => "user_id", "AND" => [ "rate[>]" => 50 ] ]
LEFT JOIN "comment" ON "post"."author_id" = "comment"."user_id" AND "rate" > 50
Raw オブジェクトを使った JOIN
"[>]account" => Medoo::raw("ON <post.author_id> = <account.user_id>")
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"
データマッピング
返されるデータ構造は自由に組み替えられます。マッピングキーは元のカラム名と一致している必要はなく、ネストした出力にも対応しています。
$data = $database->select("post", [
"[>]account" => ["user_id"]
], [
"post.content",
"userData" => [
"account.user_id",
"account.email",
"meta" => [
"account.location",
"account.gender"
]
]
], [
"LIMIT" => [0, 2]
]);
echo json_encode($data);
[
{
"content": "Hello world!",
"userData": {
"user_id": "1",
"email": "foo@example.com",
"meta": {
"location": "New York",
"gender": "male"
}
}
},
{
"content": "Hey everyone",
"userData": {
"user_id": "2",
"email": "bar@example.com",
"meta": {
"location": "London",
"gender": "female"
}
}
}
]
インデックス付きマッピング
カラム定義の先頭キーにカラム名を使うと、そのカラムの値をキーにした配列として結果を返せます。
$data = $database->select("post", [
"user_id" => [
"nickname",
"location",
"email"
]
]);
{
"10": {
"nickname": "foo",
"location": "New York",
"email": "foo@example.com"
},
"12": {
"nickname": "bar",
"location": "New York",
"email": "bar@medoo.in"
}
}
データ型の宣言
選択したフィールドの出力タイプを明示的に宣言できます。
// サポートされるデータ型: [String | Bool | Int | Number | Object | JSON]
// [String] はすべての出力値でデフォルトの型です。
// [Object] は serialize() でシリアライズされた PHP データを unserialize() で復元します。
// [JSON] は有効な JSON データとして扱われ、json_decode() でデコードされます。
$data = $database->select("post", [
"[>]account" => ["user_id"]
], [
"post.post_id",
"profile" => [
"account.age [Int]",
"account.is_locked [Bool]",
"account.userData [JSON]"
]
]);
echo json_encode($data);
[
{
"post_id": "1",
"profile": {
"age": 20,
"is_locked": true,
"userData": ["foo", "bar", "tim"]
}
},
{
"post_id": "2",
"profile": {
"age": 25,
"is_locked": false,
"userData": ["mydata1", "mydata2"]
}
}
]
// オブジェクトをデータベースに保存し、あとで取り出します。
class Foo {
var $bar = "cat";
public function __wakeup()
{
$this->bar = "dog";
}
}
$object_data = new Foo();
$database->insert("account", [
"data" => $object_data
]);
$data = $database->select("account", [
"data [Object]"
]);
echo $data[0]["data"]->bar;
// unserialize() の実行中にオブジェクトの __wakeup() メソッドが呼び出されます。
// そのため、出力は "dog" になります。
別名
カラム名やテーブル名に別名を付けることができます。JOIN を含むクエリで名前の衝突を避けたり、出力をわかりやすくしたりするのに便利です。
$data = $database->select("account", [
"user_id",
"nickname (my_nickname)"
]);
// 結果例:
// array(
// [0] => array(
// "user_id" => "1",
// "my_nickname" => "foo"
// ),
// [1] => array(
// "user_id" => "2",
// "my_nickname" => "bar"
// )
// )
$data = $database->select("post (content)", [
"[>]account (user)" => "user_id",
], [
"content.user_id (author_id)",
"user.user_id"
]);
// 結果例:
// array(
// [0] => array(
// "author_id" => "1",
// "user_id" => "321"
// ),
// [1] => array(
// "author_id" => "2",
// "user_id" => "322"
// )
// )
SELECT
"content"."user_id" AS "author_id",
"user"."user_id"
FROM
"post" AS "content"
LEFT JOIN "account" AS "user" USING ("user_id")
DISTINCT
選択したカラムに
DISTINCT キーワードを追加するには、カラム名の先頭に @ を付けます。$data = $database->select("account", [
// この列に DISTINCT が適用されます。
"@location",
"id",
"name",
]);
SELECT DISTINCT "location", "id", "name" FROM "account"
重複を除いた値を数えるには、Raw 式を使用します。
$data = $database->select("account", [
"unique_locations" => Medoo::raw("COUNT(DISTINCT <location>)")
]);
SELECT COUNT(DISTINCT "location") AS "unique_locations" FROM "account"