VI Tiếng Việt
Phiên bản: v2.3.0

select

Lấy dữ liệu từ bảng.

select($table, $columns)
select($table, $columns, $where)
select($table, $join, $columns, $where)
Giá trị trả về
[array] Mảng kết quả đã lấy.
Bạn có thể dùng * cho tham số columns để lấy tất cả các cột; tuy nhiên, để có hiệu năng và khả năng đọc tốt hơn, nên chỉ định rõ những cột thực sự cần thiết.
$data = $database->select("account", [
	"user_name",
	"email"
], [
	"user_id[>]" => 100
]);

// Kết quả ví dụ:
// array(
//  [0] => array(
//	  "user_name" => "foo",
//	  "email" => "foo@bar.com"
//  ),
//  [1] => array(
//	  "user_name" => "cat",
//	  "email" => "cat@dog.com"
//  )
// )

foreach ($data as $item) {
	echo "Người dùng: " . $item["user_name"] . " - Địa chỉ email: " . $item["email"] . "<br/>";
}

// Chọn tất cả các cột.
$data = $database->select("account", "*");

// Chọn một cột duy nhất.
$data = $database->select("account", "user_name");

// Kết quả ví dụ:
// array(
//  [0] => "foo",
//  [1] => "cat"
// )

Lấy từng dòng bằng callback

Theo mặc định, select() tải toàn bộ kết quả vào bộ nhớ và trả về dưới dạng mảng.
Khi truy xuất số lượng lớn hàng, cách này có thể làm tăng đáng kể mức sử dụng bộ nhớ. Nếu bạn truyền một callback, chẳng hạn function ($data) {}, làm tham số cuối cùng cho select(), Medoo sẽ nạp và xử lý từng hàng ngay lập tức thay vì giữ toàn bộ kết quả trong bộ nhớ trước.
Cách làm này tiết kiệm bộ nhớ hơn khi xử lý tập dữ liệu lớn.
$database->select("account", ["name"], function ($data) {
	echo $data["name"];
});

$database->select("account", [
	"name"
], function ($data) {
	echo $data["name"];
});
Điểm chuẩn hiệu suất
Ví dụ sau so sánh mức sử dụng bộ nhớ khi tìm nạp và xuất 1.000, 5.000 và 20.000 hàng từ cơ sở dữ liệu MySQL. Mức sử dụng bộ nhớ được đo bằng memory_get_usage().
// Cách 1
$database->select("account", ["name"], function ($data) {
	echo $data["name"];
});

// So sánh với:

// Cách 2
$data = $database->select("account", ["name"]);

foreach ($data as $item) {
	echo $item["name"];
}
Phương pháp 1 Phương pháp 2
1.000 bản ghi 789 KB 1,2 MB
5.000 bản ghi 1,1 MB 3,3 MB
20.000 bản ghi 2,26 MB 11,1 MB

JOIN giữa các bảng

Mệnh đề JOIN trong SQL dùng để kết hợp các hàng từ nhiều bảng. Medoo cung cấp cú pháp đơn giản để xây dựng các phép JOIN.
$database->select("post", [
	// Xác định mối quan hệ giữa bảng chính và bảng được JOIN.
	"[>]account" => ["author_id" => "user_id"]
], [
	"post.title",
	"account.city"
]);
Cột author_id trong bảng post được nối với cột user_id trong bảng account.
"[>]account" => ["author_id" => "user_id"]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"
Nếu cả hai bảng sử dụng cùng tên cột, bạn có thể sử dụng dạng viết tắt.
"[>]album" => "user_id"
LEFT JOIN "album" USING ("user_id")
Nếu nhiều cột có cùng tên trong cả hai bảng, bạn có thể chuyển chúng dưới dạng mảng.
"[>]photo" => ["user_id", "avatar_id"]
LEFT JOIN "photo" USING ("user_id", "avatar_id")
Nếu cần JOIN cùng một bảng nhiều lần, hãy gán bí danh cho bảng đã JOIN.
"[>]account (replier)" => ["replier_id" => "user_id"]
LEFT JOIN "account" AS "replier" ON "post"."replier_id" = "replier"."user_id"
Bạn cũng có thể tham chiếu một bảng đã JOIN trước đó bằng cách thêm tên bảng vào trước tên cột.
"[>]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"
Nhiều điều kiện 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"
Điều kiện JOIN bổ sung
Bạn cũng có thể thêm các điều kiện logic vào mệnh đề nối.
"[>]comment" => [
	"author_id" => "user_id",
	"AND" => [
		"rate[>]" => 50
	]
]
LEFT JOIN "comment" ON "post"."author_id" = "comment"."user_id" AND "rate" > 50
JOIN với đối tượng Raw
"[>]account" => Medoo::raw("ON <post.author_id> = <account.user_id>")
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"

Ánh xạ dữ liệu

Bạn có thể tùy chỉnh cấu trúc của dữ liệu trả về. Khóa ánh xạ không cần khớp với tên cột ban đầu và đầu ra lồng nhau được hỗ trợ.
$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"
			}
		}
	}
]

Ánh xạ theo khóa

Nếu bạn dùng tên cột làm khóa đầu tiên trong phần định nghĩa cột, kết quả sẽ được lập chỉ mục theo giá trị của cột đó.
$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"
	}
}

Khai báo kiểu dữ liệu

Bạn có thể khai báo rõ ràng kiểu đầu ra cho các cột đã chọn.
// Các kiểu dữ liệu được hỗ trợ: [String | Bool | Int | Number | Object | JSON]
// [String] là kiểu mặc định cho mọi giá trị đầu ra.
// [Object] là dữ liệu PHP được serialize() và khôi phục bằng unserialize().
// [JSON] là dữ liệu JSON hợp lệ và sẽ được giải mã bằng 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"]
		}
	}
]
// Lưu một đối tượng vào cơ sở dữ liệu rồi lấy lại sau đó.
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;

// Phương thức __wakeup() của đối tượng sẽ được gọi trong quá trình unserialize().
// Vì vậy, kết quả đầu ra sẽ là "dog".

Bí danh

Bạn có thể gán bí danh cho tên cột hoặc tên bảng. Điều này đặc biệt hữu ích trong các truy vấn JOIN để tránh xung đột tên hoặc làm cho kết quả đầu ra rõ ràng hơn.
$data = $database->select("account", [
	"user_id",
	"nickname (my_nickname)"
]);

// Kết quả ví dụ:
// 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"
]);

// Kết quả ví dụ:
// 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

Để thêm từ khóa DISTINCT vào cột đã chọn, hãy đặt tiền tố @ vào tên cột.
$data = $database->select("account", [
	// DISTINCT sẽ được áp dụng cho cột này.
	"@location",
	
	"id",
	"name",
]);
SELECT DISTINCT "location", "id", "name"
FROM "account"
Để đếm các giá trị riêng biệt, hãy dùng biểu thức Raw.
$data = $database->select("account", [
	"unique_locations" => Medoo::raw("COUNT(DISTINCT <location>)")
]);
SELECT COUNT(DISTINCT "location") AS "unique_locations"
FROM "account"