Còn lại Tham gia với khoản nào


162

Tôi cần truy xuất tất cả các cài đặt mặc định từ bảng cài đặt nhưng cũng lấy cài đặt ký tự nếu tồn tại cho ký tự x.

Nhưng truy vấn này chỉ truy xuất các cài đặt trong đó ký tự là = 1, không phải là cài đặt mặc định nếu người dùng chưa giải quyết bất kỳ ai.

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

Vì vậy, tôi cần một cái gì đó như thế này:

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

Trong đó khóa 1 và 2 là các giá trị mặc định khi khóa 0 chứa giá trị mặc định với giá trị ký tự.

Câu trả lời:


344

Các wherekhoản được lọc đi hàng nơi left joinkhông thành công. Di chuyển nó đến tham gia:

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

Khi thực hiện OUTER THAM GIA (ANSI-89 hoặc ANSI-92), vị trí lọc quan trọng vì các tiêu chí được chỉ định trong ONmệnh đề được áp dụng trước khi THAM GIA được thực hiện . Các tiêu chí đối với bảng OUTER THAM GIA được cung cấp trong WHEREmệnh đề được áp dụng sau khi THAM GIA được thực hiện . Điều này có thể tạo ra các tập kết quả rất khác nhau. Trong khi đó, nó không quan trọng đối với bên tham gia nếu các tiêu chuẩn được cung cấp trong ONhoặc WHEREkhoản - kết quả sẽ là như vậy.

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

21

Nếu tôi hiểu chính xác câu hỏi của bạn, bạn muốn có các bản ghi từ cơ sở dữ liệu cài đặt nếu chúng không có liên kết với bảng character_sinstall hoặc nếu bản ghi đã tham gia đó có character_id = 1.

Do đó bạn nên làm

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
Rủi ro đó trả lại kết quả dương tính giả
OMG Ponies

1
@OMGPonies Tôi không hiểu, trường hợp nào có rủi ro. Trong trường hợp của tôi, tôi đã áp dụng AND với tham gia và không có kết quả nào ở đó, nhưng khi tôi sử dụng giải pháp trên, tôi đã có kết quả. Nhưng tôi muốn chắc chắn về các vấn đề tôi có thể gặp phải với tùy chọn này.
Chetan Sharma

2

Bạn có thể thấy dễ hiểu hơn bằng cách sử dụng một truy vấn con đơn giản

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`

Truy vấn con được phép trả về null, vì vậy bạn không phải lo lắng về THAM GIA / WHERE trong truy vấn chính.

Đôi khi, điều này hoạt động nhanh hơn trong MySQL, nhưng so sánh nó với biểu mẫu LEFT THAM GIA để xem những gì phù hợp nhất với bạ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

Kết quả là chính xác dựa trên câu lệnh SQL. Tham gia bên trái trả về tất cả các giá trị từ bảng bên phải và chỉ khớp các giá trị từ bảng bên trái.

Các cột ID và NAME nằm từ bảng bên phải, do đó được trả về.

Điểm là từ bảng bên trái và 30 được trả về, vì giá trị này liên quan đến Tên "Dòng chảy". Các tên khác là NULL vì chúng không liên quan đến Tên "Dòng chảy".

Dưới đây sẽ trả về kết quả mà bạn đang mong đợi:

    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 áp dụng một bộ lọc trên bảng bên phải.


0

Đối với vấn đề này, như đối với nhiều người khác liên quan đến các phép nối trái không tầm thường như nối trái trên các bảng tham gia bên trong, tôi thấy thuận tiện và dễ đọc hơn khi phân tách truy vấn với withmệnh đề. Trong ví dụ của bạn,

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.