如何在不使用 SQL 中的多个连接条件的情况下获取同一行中的所有值?
Posted
技术标签:
【中文标题】如何在不使用 SQL 中的多个连接条件的情况下获取同一行中的所有值?【英文标题】:How get all value in same row without using multiple joins conditions in SQL? 【发布时间】:2020-11-26 20:16:03 【问题描述】:我有下面的表结构
学生
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(+)
如果有任何其他优化方式来获取所有用户价值,请告诉我。 注意:此表结构不能更改,只有读取权限可用
【问题讨论】:
【参考方案1】:您可以为此使用 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 turn values into columns,所以我猜你没有找到它,因为你不知道如何打电话给这个。不能怪你。
【讨论】:
以上是关于如何在不使用 SQL 中的多个连接条件的情况下获取同一行中的所有值?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用左连接的情况下根据“OR”条件对数据框进行子集化? [复制]