SQL - KIRI GABUNG beberapa kondisi - prioritas

Saya memiliki 2 tabel dengan struktur serupa dengan ini:

tabel: pengguna

field: id, active_office_address_id (bisa 0)

tabel: alamat_pengguna

bidang: id, user_id, ketik (rumah, kantor)

Seorang pengguna dapat memiliki alamat "rumah" (tidak wajib) dan beberapa alamat "kantor". Saya bergabung untuk mendapatkan alamat pengguna, tetapi saya ingin jika pengguna memiliki alamat "rumah" untuk mendapatkan alamat itu, bukan alamat "kantor".

Jadi, bagaimana saya bisa mendapatkan alamat "rumah" jika ada, dan hanya jika alamat itu tidak ada untuk mendapatkan alamat "kantor". (Pada kenyataannya, kuerinya jauh lebih rumit dan penggabungan dilakukan pada 4-5 tabel)

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 sumber
comment
Fungsi penggabungan akan membantu Anda, dengan asumsi mysql mendukungnya.   -  person Dan Bracuk    schedule 03.12.2013
comment
@morandi3 . . . Apakah Anda ingin semua alamat kantor atau hanya satu?   -  person Gordon Linoff    schedule 03.12.2013


Jawaban (3)


Anda dapat menggunakan COALESCE() dan bergabung ke tabel alamat Anda dua kali:

  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
Mungkin perlu office.id? Tidak sepenuhnya jelas, tetapi bit yang penting adalah COALESCE() dan bergabung dua kali, karena data alamat mungkin dinormalisasi. - person Hart CO; 03.12.2013
comment
Apa itu alamat rumah.alamat dan alamat kantor? Identitas? - person morandi3; 03.12.2013
comment
Itu akan menjadi bidang alamat sebenarnya yang Anda coba kembalikan. - person Hart CO; 03.12.2013

Dua gabungan kiri dan pernyataan kasus akan memberi Anda id alamat yang Anda inginkan.

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)

Anda dapat memasukkan ini kembali sebagai sub-pilihan untuk pengguna tertentu:

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 = ?)

Ini mengasumsikan bahwa hanya ada satu alamat rumah per pengguna.

person Tom McClure    schedule 03.12.2013
comment
Ya, hanya ada satu alamat rumah per pengguna. - person morandi3; 03.12.2013

Setidaknya di SQL Server, tidak yakin tentang MySql, Anda dapat menggunakan pernyataan case dalam klausa urutan demi, misalnya:

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