TypechoJoeTheme

至尊技术网

登录
用户名
密码

如何在mysql中使用UNION和UNIONALL

2025-11-14
/
0 评论
/
31 阅读
/
正在检测是否收录...
11/14

sql
SELECT 'title' AS source, id, name, score
FROM products
WHERE name LIKE '%手机%'
AND status = 1

UNION ALL

SELECT 'keyword', id, name, keyword_score
FROM products
WHERE keywords REGEXP '手机|智能机'
AND status = 1

UNION ALL

SELECT 'description', id, name, desc_score
FROM products
WHERE description LIKE '%高性能手机%'
AND status = 1

UNION ALL

SELECT 'content', id, name, contentscore FROM productdetails
WHERE contentbody LIKE '%旗舰手机评测%' AND productid IN (SELECT id FROM products WHERE status = 1);

在这个例子中,我们使用了 UNION ALL 而非 UNION。原因在于:同一商品可能同时出现在标题和关键词的匹配结果中,这是合理的多维度命中现象,不应被去重抹除。此外,由于每个子查询都基于不同字段和权重算法计算得分,即使 ID 相同,其他字段也可能不同,强行去重反而会造成信息丢失。

然而,如果业务需求强调结果的唯一性,比如统计某段时间内所有活跃用户的集合,而这些用户可能来自订单、评论、收藏等多个渠道,则应使用 UNION 来避免重复计数:

sql SELECT user_id FROM orders WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31' UNION SELECT user_id FROM comments WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31' UNION SELECT user_id FROM favorites WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31';

这里使用 UNION 确保每个用户仅出现一次,符合“去重统计”的业务逻辑。

值得注意的是,ORDER BYLIMIT 在联合查询中的使用需格外小心。它们只能作用于整个 UNION 表达式的最终结果,不能直接用于中间子句。若需对某个分支单独排序,必须将其包裹在括号内形成派生表:

sql (SELECT id, name FROM hot_products ORDER BY clicks DESC LIMIT 5) UNION ALL (SELECT id, name FROM new_products ORDER BY created_at DESC LIMIT 5);

否则会触发语法错误。这种限制在复杂报表生成中尤为常见,开发者常因疏忽而导致查询失败。

性能调优方面,建议始终优先考虑 UNION ALL,除非确有必要去重。可以通过 EXPLAIN 命令观察执行计划:使用 UNION 时通常会出现 Using temporary; Using filesort 的提示,表明正在创建临时表并排序;而 UNION ALL 则往往更为轻量。

另外,在涉及大表连接或复杂条件筛选时,应确保相关字段已建立有效索引。例如在上述搜索示例中,namekeywordsdescription 等字段若未加索引,即便使用 UNION ALL 仍可能导致全表扫描,拖慢整体响应。

综上所述,UNIONUNION ALL 并非简单的“去重与否”之别,而是反映了两种不同的数据处理哲学。前者追求结果的整洁与精确,适用于聚合统计类场景;后者崇尚效率与直白,更适合日志合并、多源检索等高吞吐需求。真正的高手不会死记硬背规则,而是根据具体业务目标、数据特征和性能要求,灵活抉择最合适的工具。

朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/38613/(转载时请注明本文出处及文章链接)

评论 (0)