어디 조항과 왼쪽 조인


162

설정 테이블에서 모든 기본 설정을 검색해야하지만 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')
)

키 0에 문자 값이있는 기본값이 포함 된 경우 키 1 및 2가 기본값입니다.

답변:


346

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'  

55

외부 조인 (ANSI-89 또는 ANSI-92)을 만들 때 조인이 작성되기 전에ON 절에 지정된 기준 이 적용 되므로 여과 위치가 중요합니다 . 이 절에 제공된 OUTER JOIN 테이블에 대한 기준 은 JOIN이 작성된 후에 적용됩니다 . 이것은 매우 다른 결과 집합을 생성 할 수 있습니다. 이와 비교하여 or 절 에 기준이 제공되면 INNER JOIN은 중요하지 않으며 결과는 동일합니다.WHEREONWHERE

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

21

질문을 올바르게 이해하면 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

7
위험은 오탐 (false positive)을 반환하는 것을
OMG 조랑말

1
이해하지 못하는 @OMGPonies, 위험이있는 사례는 무엇입니까? 내 경우에는 조인으로 AND를 적용했지만 결과가 없었지만 위의 솔루션을 사용하면 결과가있었습니다. 그러나이 옵션으로 직면 할 수있는 문제에 대해 확신하고 싶습니다.
Chetan Sharma

2

간단한 하위 쿼리를 사용하면 이해하기 쉬울 수 있습니다

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'

1

결과는 SQL 문에 따라 정확합니다. 왼쪽 조인은 오른쪽 테이블의 모든 값과 왼쪽 테이블의 일치하는 값만 반환합니다.

ID 및 NAME 열은 오른쪽 테이블에 있으므로 반환됩니다.

이 값은 Name "Flow"와 관련되어 있으므로 왼쪽 표의 점수이며 30이 반환됩니다. 다른 Name은 Name "Flow"와 관련이 없으므로 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은 오른쪽 테이블에 필터를 적용합니다.


0

이 문제의 경우 내부 조인 테이블의 왼쪽 조인과 같이 사소한 왼쪽 조인과 관련된 많은 다른 사람들과 마찬가지로 쿼리를 with절로 분할하는 것이 편리하고 읽기 쉽습니다. 귀하의 예에서

with settings_for_char as (
  select setting_id, value from character_settings where character_id = 1
)
select
  settings.*,
  settings_for_char.value
from
  settings
  left join settings_for_char on settings_for_char.setting_id = settings.id;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.