Left Join With Where Clause
Мне нужно получить все настройки по умолчанию из таблицы настроек, а также захватить настройку символа, если существует для символа x.
Но этот запрос извлекает только те настройки, где символ = 1, а не настройки по умолчанию, если пользователь havent установил кого-либо.
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 содержит значение по умолчанию с символьным значением.
Ответы
Ответ 1
Предложение where
отфильтровывает строки, где left 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'
Ответ 2
При создании ВНУТРЕННИХ СОЕДИНЕНИЙ (ANSI-89 или ANSI-92), место фильтрации имеет значение, потому что критерии, указанные в предложении ON
, применяются до того, как JOIN сделан. Критерий в отношении таблицы OUTER JOINed, указанной в предложении WHERE
, применяется после создания JOIN. Это может привести к очень различным наборам результатов. Для сравнения это не имеет значения для INNER JOINs, если критерии указаны в предложениях 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
Ответ 3
Если я правильно понял ваш вопрос, вы хотите, чтобы записи из базы данных параметров, если у них нет присоединения к таблице 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
Ответ 4
Вам может быть проще понять, используя простой подзапрос
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, но сравнивайте его с формой LEFT JOIN, чтобы увидеть, что лучше всего подходит вам.
SELECT s.*, c.value
FROM settings s
LEFT JOIN character_settings c ON c.setting_id = s.id AND c.character_id = '1'
Ответ 5
Результат корректен на основе оператора SQL. Left join возвращает все значения из правой таблицы и только соответствующие значения из левой таблицы.
Идентификаторы и столбцы NAME находятся из правой таблицы, поэтому они возвращаются.
Показатель из левой таблицы, и возвращается 30, так как это значение относится к названию "Поток". Другие имена NULL, поскольку они не относятся к названию "Поток".
Ниже приведен результат, который вы ожидали:
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 применяет фильтр в правой таблице.