Левое Соединение С Предложением Where

мне нужно получить все настройки по умолчанию из таблицы настроек, но также захватить настройку символов, если она существует для символа X.

но этот запрос извлекает только те настройки, где символ = 1, а не настройки по умолчанию, если пользователь никого не установил.

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

Так мне нужно что-то вроде этого:

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

где ключ 1 и 2-значения по умолчанию, когда ключ 0 содержит значение по умолчанию со значением символа.

5 ответов


на where предложение фильтрует строки, где left join не получится. Переместите его в join:

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

при создании внешних соединений (ANSI-89 или ANSI-92) местоположение фильтрации имеет значение, потому что критерии, указанные в ON пункт применяется перед соединением. Критерии против внешней присоединенной таблицы, представленной в WHERE пункт применяется после того, как соединение сделано. Это может привести к очень различным наборам результатов. Для сравнения, для внутренних соединений не имеет значения, если критерии указаны в ON или WHERE предложения -- результатом будет тот же.

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

Если я правильно понимаю ваш вопрос, вам нужны записи из базы данных настроек, Если у них нет соединения с таблицей character_settings или если эта объединенная запись имеет character_id = 1.

поэтому вы должны сделать

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

возможно, Вам будет легче понять, используя простой подзапрос

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`

подзапросу разрешено возвращать null, поэтому вам не нужно беспокоиться о JOIN/WHERE в основном запросе.

иногда, это работает быстрее в MySQL, но сравните его с левой формой соединения, чтобы увидеть, что лучше всего работает для вас.

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

результат правильный на основе инструкции SQL. LEFT join возвращает все значения из правой таблицы и только соответствующие значения из левой таблицы.

столбцы ID и NAME находятся в правой боковой таблице, поэтому возвращаются.

Оценка из левой таблицы, и 30 возвращается, так как это значение относится к имени "поток". Другие имена являются нулевыми, поскольку они не относятся к имени "Flow".

ниже будет возвращен результат, который вы были ожидая:

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

SQL применяет фильтр в правой таблице.