web-dev-qa-db-fra.com

Left Join avec Where Clause

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.

139
Sein Kraft

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'  
304
Andomar

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
52
OMG Ponies

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
17
Mark

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'
2
RichardTheKiwi

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.

1
Dan