Je dois récupérer tous les paramètres par défaut à partir du tableau des paramètres, mais aussi saisir le paramètre de caractère s'il existe pour le caractère x.
Mais cette requête ne récupère que les paramètres dont le caractère est = 1, et non les paramètres par défaut si l'utilisateur n'a défini personne.
SELECT `settings`.*, `character_settings`.`value`
FROM (`settings`)
LEFT JOIN `character_settings`
ON `character_settings`.`setting_id` = `settings`.`id`
WHERE `character_settings`.`character_id` = '1'
Donc, je devrais avoir besoin de quelque chose comme ça:
array(
'0' => array('somekey' => 'keyname', 'value' => 'thevalue'),
'1' => array('somekey2' => 'keyname2'),
'2' => array('somekey3' => 'keyname3')
)
Où clé 1 et 2 sont les valeurs par défaut lorsque la clé 0 contient la valeur par défaut avec la valeur de caractère.
La clause where
filtre les lignes pour lesquelles le left join
ne réussit pas. Déplacez-le à la jointure:
SELECT `settings`.*, `character_settings`.`value`
FROM `settings`
LEFT JOIN
`character_settings`
ON `character_settings`.`setting_id` = `settings`.`id`
AND `character_settings`.`character_id` = '1'
Lors de la création de jointures externes (ANSI-89 ou ANSI-92), l'emplacement de filtrage est important, car les critères spécifiés dans la clause ON
sont appliqués avant la création de la jointure. Les critères relatifs à une table OUTER JOINED fournie dans la clause WHERE
sont appliqués ne fois la jointure effectuée. Cela peut produire des ensembles de résultats très différents. En comparaison, pour les INNER JOIN si le critère est fourni dans les clauses ON
ou WHERE
, le résultat sera le même.
SELECT s.*,
cs.`value`
FROM SETTINGS s
LEFT JOIN CHARACTER_SETTINGS cs ON cs.setting_id = s.id
AND cs.character_id = 1
Si je comprends bien votre question, vous souhaitez que les enregistrements de la base de données de paramètres ne comportent pas de jointure dans la table character_settings ou si cet enregistrement joint a character_id = 1.
Tu devrais donc faire
SELECT `settings`.*, `character_settings`.`value`
FROM (`settings`)
LEFT OUTER JOIN `character_settings`
ON `character_settings`.`setting_id` = `settings`.`id`
WHERE `character_settings`.`character_id` = '1' OR
`character_settings`.character_id is NULL
Vous trouverez peut-être plus facile à comprendre en utilisant une simple sous-requête
SELECT `settings`.*, (
SELECT `value` FROM `character_settings`
WHERE `character_settings`.`setting_id` = `settings`.`id`
AND `character_settings`.`character_id` = '1') AS cv_value
FROM `settings`
La sous-requête est autorisée à renvoyer null, vous n'avez donc pas à vous soucier de JOIN/WHERE dans la requête principale.
Parfois, cela fonctionne plus rapide dans MySQL, mais comparez-le avec le formulaire LEFT JOIN pour voir ce qui vous convient le mieux.
SELECT s.*, c.value
FROM settings s
LEFT JOIN character_settings c ON c.setting_id = s.id AND c.character_id = '1'
Le résultat est correct en fonction de l'instruction SQL. La jointure gauche renvoie toutes les valeurs de la table de droite et uniquement les valeurs correspondantes de la table de gauche.
Les colonnes ID et NAME proviennent de la table de droite et sont donc renvoyées.
Le score provient de la table de gauche et 30 est renvoyé, car cette valeur se rapporte à Name "Flow". Les autres noms sont NULL car ils ne sont pas liés au nom "Flux".
Le résultat ci-dessous renverrait le résultat que vous attendiez:
SELECT a.*, b.Score
FROM @Table1 a
LEFT JOIN @Table2 b
ON a.ID = b.T1_ID
WHERE 1=1
AND a.Name = 'Flow'
Le SQL applique un filtre sur la table de droite.