Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wählen Sie eine Aufnahme basierend auf dem Meta aus

Um diese Abfrage nur in SQL zu schreiben, würden Sie etwas wie

schreiben
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

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 .