在需多种JOIN类型的场景下,能否避免使用UNION?
优化多类型子表的查询方案(无需重复UNION)
这个问题确实很头疼——每次新增物品类型就要加一段UNION,时间长了查询语句会变得臃肿不堪。针对你现有的表结构,这里有两种不用重复写UNION的优化思路,扩展性和效率都更好:
方案1:用子表合并统一关联
先把所有已售的物品记录(按类型区分)合并成一个临时数据集,再和things表关联,最后过滤颜色和类型的匹配规则:
SELECT t.name, t.type FROM things t JOIN ( -- 这里集中所有类型的已售记录,新增类型只需要加一行UNION ALL SELECT thing_id, 'book' AS item_type FROM books WHERE sold = true UNION ALL SELECT thing_id, 'cd' AS item_type FROM cds WHERE sold = true -- 比如新增pcs:SELECT thing_id, 'pc' AS item_type FROM pcs WHERE sold = true ) sold_items ON t.id = sold_items.thing_id AND t.type = sold_items.item_type -- 确保类型匹配,避免跨类型关联 WHERE (t.type = 'book' AND t.color = 'black') OR (t.type = 'cd' AND t.color = 'white') -- 新增类型的颜色规则:OR (t.type = 'pc' AND t.color = 'xxx')
优点:
- 主查询逻辑固定,新增类型只需要在子查询里加一行
UNION ALL,维护成本低 UNION ALL比UNION效率更高(不需要去重,而每个物品只会属于一种类型,不会有重复)- 可以给每个子表的
thing_id + sold加组合索引,进一步提升子查询的效率
方案2:多表LEFT JOIN + 条件过滤
直接给每个物品类型表做LEFT JOIN,然后在WHERE条件里针对不同类型匹配颜色和已售状态:
SELECT t.name, t.type FROM things t LEFT JOIN books b ON t.id = b.thing_id AND t.type = 'book' -- 只关联书籍类型的记录 LEFT JOIN cds c ON t.id = c.thing_id AND t.type = 'cd' -- 只关联CD类型的记录 -- 新增类型:LEFT JOIN pcs p ON t.id = p.thing_id AND t.type = 'pc' WHERE -- 黑色且已售的书籍 (t.type = 'book' AND t.color = 'black' AND b.sold = true) -- 白色且已售的CD OR (t.type = 'cd' AND t.color = 'white' AND c.sold = true) -- 新增类型规则:OR (t.type = 'pc' AND t.color = 'xxx' AND p.sold = true)
优点:
- 完全不用UNION,逻辑直观易懂
- 每个JOIN都加了
type过滤,不会产生多余的关联数据,效率有保障
额外建议
如果后续会频繁新增物品类型,最好能重构表结构:比如创建一个统一的sold_items表,包含thing_id、sold字段,或者直接把sold字段移到things表(如果所有物品都有“是否售出”的属性)。这样就能彻底避免多表关联的麻烦,查询会更简洁高效。
内容的提问来源于stack exchange,提问作者troubadour
相关产品推荐
相关产品推荐

