SQL - LEFT JOIN หลายเงื่อนไข - ลำดับความสำคัญ

ฉันมี 2 ตารางที่มีโครงสร้างคล้ายกับสิ่งนี้:

ตาราง: ผู้ใช้

สาขา: id, active_office_address_id (อาจเป็น 0)

ตาราง: user_address

ฟิลด์: id, user_id, ประเภท (บ้าน, สำนักงาน)

ผู้ใช้สามารถมีที่อยู่ "บ้าน" (ไม่บังคับ) และมีที่อยู่ "สำนักงาน" ได้หลายรายการ ฉันมีการเข้าร่วมเพื่อรับที่อยู่ผู้ใช้ แต่ฉันต้องการว่าหากผู้ใช้มีที่อยู่ "บ้าน" เพื่อรับที่อยู่นั้น ไม่ใช่ที่อยู่ "สำนักงาน"

ดังนั้น ฉันจะรับที่อยู่ "บ้าน" ได้อย่างไร ถ้ามี และเฉพาะในกรณีที่ไม่มีอยู่เพื่อรับที่อยู่ "สำนักงาน" (ในความเป็นจริงแบบสอบถามมีความซับซ้อนกว่ามากและการรวมเสร็จสิ้นใน 4-5 ตาราง)

SELECT * FROM user LEFT JOIN user_address ON (user.id = address.user_id AND 
(user_address.type = "home" OR user.active_office_address_id = user_address.id))
group by user.id

person morandi3    schedule 03.12.2013    source แหล่งที่มา
comment
ฟังก์ชัน Coalesce จะช่วยคุณได้ โดยสมมติว่า mysql รองรับ   -  person Dan Bracuk    schedule 03.12.2013
comment
@morandi3 . . . คุณต้องการที่อยู่สำนักงานทั้งหมดหรือเพียงอันเดียว?   -  person Gordon Linoff    schedule 03.12.2013


คำตอบ (3)


คุณสามารถใช้ COALESCE() และเข้าร่วมในตารางที่อยู่ของคุณสองครั้ง:

  SELECT user.id
       ,COALESCE(home.address, office.address) AS Address
  FROM user 
  LEFT JOIN user_address AS home
     ON user.id = home.user_id 
       AND home.type = "home"
  LEFT JOIN user_address AS office
     ON user.active_office_address_id = office.user_id 
  GROUP BY user.id
person Hart CO    schedule 03.12.2013
comment
อาจจำเป็นต้องมี office.id? ไม่ชัดเจนทั้งหมด แต่บิตที่สำคัญคือ COALESCE() และเชื่อมต่อสองครั้ง เนื่องจากข้อมูลที่อยู่น่าจะเป็นมาตรฐาน - person Hart CO; 03.12.2013
comment
home.address และ office.address คืออะไร ไอดี? - person morandi3; 03.12.2013
comment
ซึ่งจะเป็นช่องที่อยู่จริงที่คุณพยายามส่งคืน - person Hart CO; 03.12.2013

การรวมสองรายการที่เหลือและคำสั่ง case จะให้รหัสที่อยู่ที่คุณต้องการ

SELECT user.*,CASE WHEN home_addr.id IS NOT NULL THEN home_addr.id ELSE ofc_addr.id END AS addr_id
FROM user
LEFT JOIN user_address AS home_addr
  ON (user.id = home_addr.user_id AND home_addr.type = 'home')
LEFT JOIN user_address AS ofc_addr
  ON (user.active_office_address_id = ofc_addr.id)

คุณสามารถป้อนกลับเป็นตัวเลือกย่อยสำหรับผู้ใช้รายใดรายหนึ่งได้:

SELECT * FROM user LEFT JOIN user_address
WHERE user.id = ?
AND user_address.user_id = user.id
AND user_address.id IN
    (SELECT CASE WHEN home_addr.id IS NOT NULL THEN home_addr.id ELSE ofc_addr.id END AS addr_id
    FROM user
    LEFT JOIN user_address AS home_addr
      ON (user.id = home_addr.user_id AND home_addr.type = 'home')
    LEFT JOIN user_address AS ofc_addr
      ON (user.active_office_address_id = ofc_addr.id)
    WHERE user.id = ?)

ถือว่ามีที่อยู่บ้านเพียงแห่งเดียวต่อผู้ใช้หนึ่งราย

person Tom McClure    schedule 03.12.2013
comment
ใช่ มีที่อยู่บ้านเพียงแห่งเดียวต่อผู้ใช้หนึ่งราย - person morandi3; 03.12.2013

อย่างน้อยใน SQL Server หากไม่แน่ใจเกี่ยวกับ MySql คุณสามารถใช้คำสั่ง case ตามลำดับได้ เช่น

order by user.id, case user_address.type when 'home' then 1 else 2 end, --additional ordering clauses here
person beercodebeer    schedule 03.12.2013