Oracle将多个查询结果以列的形式合并在一起

本文介绍了如何在Oracle中通过rownum和完全外连接将部门平均工资、岗位平均工资以及部门岗位平均工资这三种查询结果以列的形式合并在一起,解决了将多个查询结果在同一查询中展示的问题。核心思路是利用rownum和全外连接,避免了union等操作带来的行合并效果。

--问题:查询部门的平均工资 岗位的平均工资 每个部门的每个岗位的平均工资

且将其在一个查询中展示

 

思路:首先分别查出这三张表 假设为A B C 然后利用两两结合 先将A B结合由于它

们之间没有任何关系 所以想要连接它们需要使用rownum 利用完全外连接和rownum相等 使A B表以字段的形式(而不是以行的形式)连接在一起这样的话就可以实现将不同表中的数据以列的形式合并在一起(之所以这么 麻烦是因为union union all minus intersect是以行的形式将多个查询结果合并在一起的 想要实现以列的形式将多个查询结果合并在一起的话就需要借助rownum和(完全)外连接来实现) 解决这个问题的核心就是rownum和完全外连接

    具体代码:

    select e3.部门平均工资, e3.岗位平均工资, e44.部门岗位平均工资 from         

            (select e11.部门平均工资, e22.岗位平均工资, rownum rn from

                (select e1.部门平均工资, rownum rn from

                    (select avg(sal) 部门平均工资 from

                        emp group bydeptno)e1)e11

                full join

                (select e2.岗位平均工资, rownum rn from

                    (select avg(sal) 岗位平均工资 from

                         emp group by job)e2)e22

                on e11.rn = e22.rn)e3

            full join

            (select e4.*, rownum rn from

                (select avg(sal) 部门岗位平均工资 from

                    emp group by deptno,job)e4)e44

            on e3.rn = e44.rn;

<think>我们讨论了如何将多个SELECT语句的结果合并到同一个查询结果中。在Oracle数据库中,常用的方法是使用集合操作符(如UNION、UNION ALL)或使用JOIN操作(如果结果有关联字段)。此外,还可以使用子查询或WITH子句(公共表表达式)来组织多个查询。 根据引用[5],其中提到了使用CASE语句在单个SELECT中根据条件统计不同情况的数量,但这不是直接合并多个独立查询结果。不过,我们可以借鉴这种思路,如果多个查询是针对同一数据源的不同条件,则可以使用条件聚合。但如果多个查询是完全独立的(来自不同的表或没有关联),则需要使用集合操作。 具体方法如下: 1. **使用UNION或UNION ALL操作符**: - 当多个SELECT语句返回相同数量和类型的时,可以使用UNION(去重)或UNION ALL(不去重)将它们纵向合并。 - 注意:每个SELECT语句的名可以不同,但的数量和数据类型必须匹配(或可隐式转换)。结果集的名通常以第一个SELECT语句的名为准。 2. **使用JOIN操作**: - 如果多个查询结果有相关联的字段(如ID),则可以使用JOIN(内连接、外连接)将它们横向合并。 3. **使用子查询或WITH子句**: - 如果多个查询结果需要进一步处理,可以先将每个查询定义为子查询或使用WITH子句定义临时结果集,然后再合并。 以下通过示例说明: **示例1:使用UNION ALL合并两个独立的查询结果** 假设我们有两个表,表A和表B,我们想将两个表的某些查询结果合并到一起(假设两个查询结果都只有一且数据类型相同): ```sql SELECT column1 AS result_column FROM tableA UNION ALL SELECT columnX FROM tableB; ``` **示例2:使用JOIN横向合并** 假设我们有两个查询,一个查询得到每个部门的员工数量,另一个查询得到每个部门的平均工资,并且它们都按部门ID分组,那么我们可以通过部门ID将两个查询结果连接起来: ```sql SELECT dept_count.dept_id, dept_count.emp_count, dept_avg.avg_salary FROM (SELECT dept_id, COUNT(*) AS emp_count FROM emp GROUP BY dept_id) dept_count JOIN (SELECT dept_id, AVG(salary) AS avg_salary FROM emp GROUP BY dept_id) dept_avg ON dept_count.dept_id = dept_avg.dept_id; ``` **示例3:使用WITH子句(公用表表达式)** 如果查询比较复杂,可以先定义多个临时结果集,然后再合并: ```sql WITH query1 AS (SELECT ... FROM ...), query2 AS (SELECT ... FROM ...) SELECT * FROM query1 UNION ALL SELECT * FROM query2; ``` 但是,请注意,如果多个查询返回的不完全匹配,我们需要调整使其匹配。例如,如果第一个查询有3,第二个查询只有2,我们可以为第二个查询添加一个NULL作为第三(并指定别名),使数一致: ```sql SELECT col1, col2, col3 FROM table1 UNION ALL SELECT colA, colB, NULL AS col3 FROM table2; ``` 另外,引用[4]提到了虚表dual,当我们只需要返回一个常量值而不需要从表中读取时,可以使用dual表。例如,我们可以将多个这样的常量查询合并: ```sql SELECT 'Total Employees' AS category, COUNT(*) AS value FROM emp UNION ALL SELECT 'Total Departments', COUNT(*) FROM dept; ``` 综上所述,根据实际需求选择合适的方法。 相关问题: 1. 在Oracle中,UNION和UNION ALL有什么区别? 2. 如何合并多个查询结果并保持特定的顺序? 3. 当合并多个查询结果数不一致时,如何解决? </think>在Oracle数据库中,将多个`SELECT`语句的结果合并到同一个查询结果中,主要有以下几种方法: ### 一、使用集合操作符(推荐) Oracle提供三种集合操作符实现结果合并: 1. **UNION ALL**(保留重复行) ```sql SELECT col1, col2 FROM table1 WHERE condition1 UNION ALL SELECT colA, colB FROM table2 WHERE condition2; ``` 2. **UNION**(自动去重) ```sql SELECT employee_id FROM hr_employees UNION SELECT manager_id FROM hr_departments; ``` 3. **MINUS/INTERSECT**(差集/交集) ```sql -- 获取只在table1存在的数据 SELECT id FROM table1 MINUS SELECT id FROM table2; -- 获取两表共有数据 SELECT product_id FROM inventory INTERSECT SELECT product_id FROM orders; ``` **特点**: - 所有SELECT语句的数和数据类型必须匹配 - 最终名以第一个SELECT语句为准 - 默认按第一升序排序(可添加`ORDER BY`覆盖)[^1][^5] --- ### 二、使用JOIN操作(关联合并) 当结果集需要横向扩展时: ```sql SELECT t1.col1, t2.col2 FROM (SELECT ... FROM table1) t1 FULL OUTER JOIN (SELECT ... FROM table2) t2 ON t1.key = t2.key; ``` --- ### 三、使用PL/SQL集合(复杂场景) 通过`BULK COLLECT`和管道函数: ```sql CREATE TYPE result_obj AS OBJECT(col1 VARCHAR2(50), col2 NUMBER); CREATE TYPE result_tab AS TABLE OF result_obj; CREATE FUNCTION get_combined_data RETURN result_tab PIPELINED IS BEGIN FOR rec IN (SELECT ... FROM source1) LOOP PIPE ROW(result_obj(rec.val1, rec.val2)); END LOOP; FOR rec IN (SELECT ... FROM source2) LOOP PIPE ROW(result_obj(rec.dataA, rec.dataB)); END LOOP; RETURN; END; / -- 调用 SELECT * FROM TABLE(get_combined_data()); ``` --- ### 四、使用临时表(大数据量) ```sql CREATE GLOBAL TEMPORARY TABLE temp_combined ( col1 VARCHAR2(100), col2 DATE ) ON COMMIT DELETE ROWS; INSERT INTO temp_combined SELECT a,b FROM source1; INSERT INTO temp_combined SELECT x,y FROM source2; SELECT * FROM temp_combined; -- 合并结果 ``` --- ### 关键区别对比 | 方法 | 适用场景 | 性能 | 排序控制 | 数据类型要求 | |--------------|----------------------------|----------|----------|--------------| | UNION ALL | 简单纵向合并(保留重复) | ★★★★ | 需显式指定 | 严格匹配 | | JOIN | 关联数据横向扩展 | ★★★☆ | 灵活 | 键值匹配 | | PL/SQL管道 | 复杂业务逻辑处理 | ★★☆ | 灵活 | 自定义 | | 临时表 | 超大数据集分阶段处理 | ★★ | 完全控制 | 宽松 | > **最佳实践**:对于简单合并优先使用`UNION ALL`(比`UNION`效率高40%+),关联数据用`JOIN`,ETL处理用临时表[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值