2011-01-20 9 views
103

Necesito recuperar todos los ajustes predeterminados de la tabla de configuraciones pero también tomar la configuración de caracteres si existe para el carácter x.Unir a la izquierda con la cláusula Where

Pero esta consulta solo está recuperando aquellas configuraciones donde character = 1, no las configuraciones predeterminadas si el usuario no ha configurado a nadie.

SELECT `settings`.*, `character_settings`.`value` 
FROM (`settings`) 
LEFT JOIN `character_settings` 
ON `character_settings`.`setting_id` = `settings`.`id` 
WHERE `character_settings`.`character_id` = '1' 

así que debería necesitar algo como esto:

array(
    '0' => array('somekey' => 'keyname', 'value' => 'thevalue'), 
    '1' => array('somekey2' => 'keyname2'), 
    '2' => array('somekey3' => 'keyname3') 
) 

Cuando la tecla 1 y 2 son los valores por defecto cuando la tecla 0 contiene el valor por defecto con el valor del carácter.

Respuesta

240

La cláusula where está filtrando las filas donde el left join no funciona. Moverlo a la unión:

SELECT `settings`.*, `character_settings`.`value` 
FROM `settings` 
LEFT JOIN 
     `character_settings` 
ON  `character_settings`.`setting_id` = `settings`.`id` 
     AND `character_settings`.`character_id` = '1' 
12

Si entiendo bien su pregunta desea que los registros de la base de valores si no tienen una unión al otro lado de la mesa character_settings o si ese registro se unió ha character_id = 1.

debe, por tanto, hacer

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 
+4

Que corre el riesgo de devolver falsos positivos –

+0

@OMGPonies No entiendo, lo que podría ser el caso de que tenga riesgos. En mi caso apliqué el AND con join y no encontré ningún resultado, pero cuando utilicé la solución anterior, obtuve resultados. Pero quiero estar seguro sobre los problemas que puedo enfrentar con esta opción. –

+0

Gracias. Buena respuesta. –

41

al realizar combinaciones externas (ANSI-89 o ANSI-92), las cuestiones de localización de filtración debido a los criterios especificados en la cláusula ON se aplica antes de la unión se hizo. Los criterios contra una tabla OUTER JOINed proporcionada en la cláusula WHERE se aplica después de que se haya realizado el JOIN. Esto puede producir conjuntos de resultados muy diferentes. En comparación, no importa para INNER JOINs si el criterio se proporciona en las cláusulas ON o WHERE; el resultado será el mismo.

SELECT s.*, 
      cs.`value` 
    FROM SETTINGS s 
LEFT JOIN CHARACTER_SETTINGS cs ON cs.setting_id = s.id 
           AND cs.character_id = 1 
1

Puede que le resulte más fácil de comprender mediante el uso de una sub consulta sencilla

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` 

Se permite que la subconsulta para devolver null, por lo que no tiene que preocuparse de JOIN/WHERE en la consulta principal .

A veces, esto funciona más rápido en MySQL, pero compárelo con el formulario LEFT JOIN para ver qué funciona mejor para usted.

SELECT s.*, c.value 
FROM settings s 
LEFT JOIN character_settings c ON c.setting_id = s.id AND c.character_id = '1' 
0

El resultado es correcto según la declaración de SQL. La combinación izquierda devuelve todos los valores de la tabla correcta y solo los valores coincidentes de la tabla izquierda.

Las columnas ID y NAME se muestran en la tabla lateral derecha, por lo que se devuelven.

La puntuación es de la tabla de la izquierda, y se devuelve 30, ya que este valor se relaciona con el nombre "Flujo". Los otros nombres son NULL ya que no se relacionan con Name "Flow".

La continuación devolvería el resultado que se esperaba:

SELECT a.*, b.Score 
FROM @Table1 a 
    LEFT JOIN @Table2 b 
     ON a.ID = b.T1_ID 
WHERE 1=1 
AND a.Name = 'Flow' 

El SQL aplica un filtro en la tabla de la derecha.

Cuestiones relacionadas