Um diese Abfrage nur in SQL zu schreiben, würden Sie etwas wie
schreibenSELECT 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
Das HAVING
-Klausel bestätigt, dass eine Aufzeichnung alle angegebenen Metaschlüssel- und Wertpaare enthält.
Um das in Ihren PHP-Code zu übersetzen, müssen Sie Ihr $where
aufbauen Klausel in ähnlicher Weise; Ich ziehe es vor, ein Array zu verwenden und zu implodieren, um mir Gedanken über nachgestellte AND
zu ersparen und dergleichen. Während wir diese Klausel erstellen, können wir gleichzeitig die Eingaben für bind_param
erstellen :
$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();
}
Eine Demo der Abfragebildung und Parametergenerierung finden Sie hier .