Where Clause ile ayrıl


162

Tüm varsayılan ayarları ayarlar tablosundan almanız gerekiyor, ancak x karakteri için varsa karakter ayarını da almam gerekiyor.

Ancak bu sorgu yalnızca karakterin = 1 olduğu ayarları alır, kullanıcı herhangi birini ayarlamamışsa varsayılan ayarları değil.

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

Yani böyle bir şeye ihtiyacım var:

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

Burada 0 tuşu, karakter değeri olan varsayılan değeri içerdiğinde, 1 ve 2 tuşlarının varsayılan değerlerdir.

Yanıtlar:


346

whereFıkra satırları uzakta filtrelediğini left joinbaşarılı olmaz. Birleşmeye taşıyı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'  

55

DIŞ BAĞLANTILAR (ANSI-89 veya ANSI-92) yapılırken, birleştirme yapılmadan önceON maddede belirtilen kriterler uygulandığından filtrasyon yeri önemlidir . Bu maddede belirtilen OUTER JOINed tablosuna karşı kriterler JOIN yapıldıktan sonra uygulanır . Bu çok farklı sonuç kümeleri üretebilir. Buna karşılık, kriterler veya cümle içinde sunuluyorsa INNER JOIN'ler için önemli değildir - sonuç aynı olacaktır.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

Sorunuzu doğru bir şekilde anlarsam, character_settings tablosunda bir birleşim yoksa veya bu birleştirilen kaydın character_id = 1'i varsa, ayarlar veritabanındaki kayıtları istersiniz.

Bu nedenle yapmalısın

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
Bu yanlış pozitif geri dönme riskleri
OMG Ponies

1
@OMGPonies Anlamıyorum, Riskleri olan durumlar neler olabilir. Benim durumumda AND'i birleştirme ile uyguladım ve hiçbir sonuç yoktu, ancak yukarıdaki çözümü kullandığımda sonuçlar elde ettim. Ancak bu seçenekle karşılaşabileceğim konulardan emin olmak istiyorum.
Chetan Sharma

2

Basit bir alt sorgu kullanarak anlaşılması daha kolay olabilir

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`

Alt sorgu null döndürmek için izin verilir, bu nedenle ana sorguda JOIN / WHERE hakkında endişelenmenize gerek yok.

Bazen, bu MySQL'de daha hızlı çalışır , ancak sizin için neyin en iyi olduğunu görmek için LEFT JOIN formuyla karşılaştırın.

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

1

Sonuç, SQL deyimine göre doğrudur. Sol birleştirme, sağ tablodaki tüm değerleri ve yalnızca sol tablodaki eşleşen değerleri döndürür.

Kimlik ve NAME sütunları sağ taraftaki tablodan alınmıştır, bu nedenle döndürülür.

Skor soldaki tablodan ve 30 değer döndürülür, çünkü bu değer "Akış" ile ilgilidir. Diğer Adlar "Akış" Adıyla ilgili olmadıklarından NULL olurlar.

Aşağıdakiler beklediğiniz sonucu döndürür:

    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, sağ taraftaki tabloya bir filtre uygular.


0

Bu sorun için, iç birleştirilen tablolarda sola birleştirme gibi önemsiz olmayan sol birleşimleri içeren diğer pek çok kişi için olduğu gibi, sorguyu bir withcümle ile bölmek uygun ve biraz daha okunabilir buluyorum . Örneğinizde,

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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.