sql >> Database >  >> RDS >> Mysql

Selecteer een opname op basis van de meta

Om deze query alleen in SQL te schrijven, zou je zoiets schrijven als

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

De HAVING clausule is wat beweert dat een opname alle gespecificeerde metasleutel- en waardeparen heeft.

Om dat in uw PHP-code te vertalen, moet u uw $where . opbouwen clausule op soortgelijke wijze; Ik geef er de voorkeur aan om een ​​array te gebruiken en te imploderen om me geen zorgen te maken over het achterblijven van AND en dergelijke. Op hetzelfde moment dat we die clausule bouwen, kunnen we de invoer bouwen naar 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();
}

Een demo van het vormen van zoekopdrachten en het genereren van parameters vindt u hier .




  1. MySQL Database-ontwerp. Rijen invoegen in 1op1 tabellen.

  2. Kan geen UTF8-tekens opslaan in MySQL

  3. Hoe Oracle te dwingen om indexbereikscan te gebruiken?

  4. Waarom kan ik SELECT ... FOR UPDATE niet gebruiken met aggregatiefuncties?