Để viết truy vấn này chỉ bằng SQL, bạn sẽ viết một cái gì đó như
SELECT r.id
FROM recording r
JOIN meta m ON m.recording_id = r.id
AND (m.meta_key = 'key1' AND m.meta_value = 'value1'
OR m.meta_key = 'key2' AND m.meta_value = 'value2'
OR m.meta_key = 'key3' AND m.meta_value = 'value3'
...)
GROUP BY r.id
HAVING COUNT(*) = <count of all key/value pairs>
LIMIT 10
HAVING
mệnh đề khẳng định rằng bản ghi có tất cả các cặp giá trị và khóa meta được chỉ định.
Để dịch mã đó sang mã PHP, bạn cần tạo $where
mệnh đề theo cách tương tự; Tôi thích sử dụng một mảng và mã hóa để đỡ lo lắng về việc theo dõi AND
và những thứ tương tự. Đồng thời khi chúng tôi đang xây dựng điều khoản đó, chúng tôi có thể xây dựng các đầu vào cho bind_param
:
$join = array();
$params = array();
$types = '';
foreach ($metas as $key => $value) {
$join[] = 'm.meta_key=? AND m.meta_value=?';
$params[] = $key;
$params[] = $value;
$types .= 'ss';
}
// add the parameter for the `HAVING` check
$params[] = count($metas);
$types .= 'i';
// add the limit
$params[] = $limit;
$types .= 'i';
// make the query string
$sql = "SELECT recording_id
FROM {$config->recording_table} r
JOIN {$config->meta_table} m ON m.recording_id = r.id
AND (" . implode(' OR ', $join) . ")
GROUP BY r.id
HAVING COUNT(*) = ?
LIMIT ?";
$stmt = $connection->prepare($sql);
if (!$stmt) {
echo "Prepare failed: " . $conn->error . "\n";
die();
}
$stmt->bind_param($types, ...$params);
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error . " \r\n";
die();
}
Bạn có thể tìm thấy bản trình diễn về hình thành truy vấn và tạo tham số tại đây .