開發(fā)中遇到這樣的一個需求:用戶表為A量愧,小區(qū)表為B钾菊,用戶小區(qū)關(guān)系通過C表多對多關(guān)聯(lián)帅矗,我們需要查詢出每一個用戶所擁有的小區(qū),以下圖的格式顯示:
在解決問題中發(fā)現(xiàn)了兩種方式可實現(xiàn)該功能煞烫,下面直接貼出sql語句
方式一
SELECT
m.user_id AS userId,
(
SELECT
GROUP_CONCAT(ca.`name` SEPARATOR '浑此、')
FROM
common_user_apartment ua
LEFT JOIN common_apartment ca ON ca.id = ua.apartment_id
WHERE
ua.user_id = m.user_id
) AS apartmentNames
FROM
basics_users m
LEFT JOIN common_apartment ca ON ca.id = m.apartment_id
LEFT JOIN common_region cr ON cr.id = ca.city_id
WHERE
m.isdel = 'N'
方式一是把查詢c表作為主表,并且left join B表的一個子查詢滞详,查出每一個用戶id擁有的小區(qū)名稱拼接結(jié)果作為擁有小區(qū)字段值的凛俱,我們看看其查詢性能
可見查詢一萬條左右數(shù)據(jù)需要17秒左右,這種速度我們顯然是不能接受的料饥,而且需要以擁有小區(qū)的名稱做模糊查詢時候也無從下手蒲犬。于是后來繼續(xù)想辦法優(yōu)化,就找到了下面的方式二岸啡。
方式二
SELECT
m.user_id AS userId,
m.user_name AS userName,
cua.apartmentNames AS apartmentNames
FROM
basics_users m
LEFT JOIN common_apartment ca ON ca.id = m.apartment_id
LEFT JOIN common_region cr ON cr.id = ca.city_id
LEFT JOIN (
SELECT
ua.user_id,
GROUP_CONCAT(
ua.apartment_id SEPARATOR ','
) AS apartmentIds,
GROUP_CONCAT(ca.`name` SEPARATOR '暖哨、') AS apartmentNames
FROM
common_user_apartment ua
LEFT JOIN common_apartment ca ON ca.id = ua.apartment_id
GROUP BY
ua.user_id
) cua ON cua.user_id = m.user_id
WHERE
m.isdel = 'N';
方式二依然有一個查詢用戶擁有小區(qū)名稱拼接結(jié)果的子查詢,只是這個子查詢不是直接作為結(jié)果字段返回凰狞,而是根據(jù)用戶id為group規(guī)則查詢出來每一個用戶的擁有小區(qū)結(jié)果字符串,然后作為A表的left join的虛擬表沛慢,下面看一下測試結(jié)果
可見同樣查詢一萬條數(shù)據(jù)一秒鐘都不用赡若,查詢速度提高了至少20倍,而且因為是虛擬關(guān)聯(lián)表团甲,可以直接用 cua.apartmentNames LIKE '%小區(qū)1%' 而實現(xiàn)模糊查詢逾冬。