oracle—如何在不使用sql中的多个联接条件的情况下获取同一行中的所有值?

lf5gs5x2  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(392)

我有下面的表结构

学生

Stud_ID | First_Name | Last_name | Contact
ID001   | AAA        | AAA       |     111
ID002   | BBB        | BBB       |     222

学生

Stud_ID | NUM | Value
ID001   |  10 | English
ID001   |  20 | Math
ID001   |  30 | Science
ID002   |  10 | English
ID002   |  20 | Math

预期产量

Stud_id | First_name | 10      | 20    | 30
ID001   | AAA        | English | Math  | Science
ID002   | BBB        | English | Math  |

我正在使用的当前查询

select 
        stud_id,
        First_name,
        EG.EGUV AS "10",
        LE.LEUV AS "20",
        FPS.FPSUV AS "30"
from 
        student,
        (SELECT STUD_ID AS EGS,USER_VALUE AS EGUV FROM STUD_USER WHERE COL_NUM='10') AS EG,
        (SELECT STUD_ID AS BUS,USER_VALUE AS BUUV FROM STUD_USER WHERE COL_NUM='20') AS BU,
        (SELECT STUD_ID AS AUS,USER_VALUE AS AUV FROM STUD_USER WHERE COL_NUM='30') AS A
where
        ST.STUD_ID=EG.EGS(+) and 
        ST.STUD_ID=BU.BUS(+) and    
        ST.STUD_ID=A.AUS(+)

请告诉我是否有任何其他优化的方法来获取所有用户值。注意:此表结构不能更改,只有读取权限可用

vs91vp4v

vs91vp4v1#

您可以使用oracle pivot子句来实现这一点。它将根据所选列的值动态地创建额外的列。
这是我使用的查询(使用with子句模拟输入数据):

WITH
Student
AS
    (SELECT 'ID001' AS Stud_ID, 'AAA' AS First_Name, 'AAA' AS Last_name, 111 AS Contact FROM DUAL
     UNION ALL
     SELECT 'ID002', 'BBB', 'BBB', 222 FROM DUAL),
StudUser
AS
    (SELECT 'ID001' AS Stud_ID, 10 AS NUM, 'English' AS VALUE FROM DUAL
     UNION ALL
     SELECT 'ID001', 20, 'Math' FROM DUAL
     UNION ALL
     SELECT 'ID001', 30, 'Science' FROM DUAL
     UNION ALL
     SELECT 'ID002', 10, 'English' FROM DUAL
     UNION ALL
     SELECT 'ID002', 20, 'Math' FROM DUAL),
Prepare
AS
    (SELECT ST.STUD_ID,
            ST.FIRST_NAME,
            SU.NUM,
            SU.VALUE
       FROM STUDENT ST LEFT JOIN STUDUSER SU ON ST.STUD_ID = SU.STUD_ID)
SELECT *
FROM Prepare PIVOT (MIN (VALUE) FOR NUM IN (10, 20, 30))

pivot函数需要一个聚合函数,因为它将遍历所有结果,例如。 STUD_ID = ID001 and NUM = 10 并将根据所使用的聚合函数返回一个值。你的例子暗示了 STUD_ID and NUM studuser表将是唯一的,因此大多数oracle的聚合函数都将这样做,因为它们只需要遍历一个值。如果组合不是唯一的,那么您必须花一点时间来考虑如何聚合它们。
pivot子句的for部分用于指定要转换为列的值。不幸的是,这不能动态生成,例如:

SELECT *
FROM Prepare PIVOT (MIN (VALUE) FOR NUM IN ( SELECT DISTINCT NUM FROM StudUser ))

这将是无效的,无法编译。
还可以为数据透视列指定所需的列名,如下所示:

SELECT *
FROM Prepare PIVOT (MIN (VALUE) FOR NUM IN (10 Subject1, 20 Subject2, 30 Subject3))

我仅仅通过搜索就找到了pivot子句:oracle将值转换为列,所以我猜您没有找到它,因为您不知道如何调用它。不能怪你。

相关问题