我的数据库中有一个名为student_info的表。有多列,其中两列存储逗号分隔值
class_id student marks
----------------------------------------------
1 tom,jam,tim 55,65,75
2 rim,gum,ram 33,66,77
我希望输出如下
class_id student marks
------------------------------------------------
1 tom 55
1 tom 65
1 tom 75
1 jam 55
1 jam 65
1 jam 75
1 tim 55
1 tim 65
1 tim 75
我的查询如下
SELECT student_id,TRIM(REGEXP_SUBSTR(student, '[^,]+', 1, level)) student_name
FROM STUDENT_INFO
CONNECT BY level <= REGEXP_COUNT(student, '[^,]+')
AND PRIOR student = student AND marks = marks
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
使用上面的查询我可以得到如下输出
class_id student_name marks
------------------------------
1 tom 55,65,75
1 jam 55,65,75
1 tim 55,65,75
如何实现所需的输出?有什么建议吗?
答案 0 :(得分:3)
规范化表比找到将csv转换为行的复杂方法要容易得多。
在这种情况下,您可以使用:
+----------+------------+-------+
| CLASS_ID | STUDENT | MARKS |
+----------+------------+-------+
| 1 | tom | 55 |
+----------+------------+-------+
| 1 | tom | 65 |
+----------+------------+-------+
| 1 | tom | 75 |
+----------+------------+-------+
| 1 | jam | 55 |
+----------+------------+-------+
| 1 | jam | 65 |
+----------+------------+-------+
| 1 | jam | 75 |
+----------+------------+-------+
| 1 | tim | 55 |
+----------+------------+-------+
| 1 | tim | 65 |
+----------+------------+-------+
| 1 | tim | 75 |
+----------+------------+-------+
| 2 | rim | 33 |
+----------+------------+-------+
| 2 | rim | 66 |
+----------+------------+-------+
| 2 | rim | 77 |
+----------+------------+-------+
| 2 | gum | 33 |
+----------+------------+-------+
| 2 | gum | 66 |
+----------+------------+-------+
| 2 | gum | 77 |
+----------+------------+-------+
| 2 | ram | 33 |
+----------+------------+-------+
| 2 | ram | 66 |
+----------+------------+-------+
| 2 | ram | 77 |
+----------+------------+-------+
产地:
Bundle bundle = new Bundle();
bundle.putString ("fields", "full_picture,message");
new GraphRequest(
AccessToken.getCurrentAccessToken(),
"{page-id}/feed",
bundle,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
/* handle the result */
Log.e("TAG", response.toString());
}
}
).executeAsync();
答案 1 :(得分:1)
分层查询:
使用相关分层查询一次查找子字符串,然后应用交叉产品加入它们:
SELECT class_id,
s.COLUMN_VALUE AS student,
m.COLUMN_VALUE AS mark
FROM table_name t,
TABLE(
CAST(
MULTISET(
SELECT REGEXP_SUBSTR( t.students, '[^,]+', 1, LEVEL )
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT( t.students, '[^,]+' )
) AS SYS.ODCIVARCHAR2LIST
)
) s,
TABLE(
CAST(
MULTISET(
SELECT TO_NUMBER( REGEXP_SUBSTR( t.marks, '[^,]+', 1, LEVEL ) )
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT( t.marks, '[^,]+' )
) AS SYS.ODCIVARCHAR2LIST
)
) m
<强>输出强>:
CLASS_ID STUDENT MARKS
-------- ------- -----
1 tom 55
1 tom 65
1 tom 75
1 jam 55
1 jam 65
1 jam 75
1 tim 55
1 tim 65
1 tim 75
2 rim 33
2 rim 66
2 rim 77
2 gum 33
2 gum 66
2 gum 77
2 ram 33
2 ram 66
2 ram 77
递归子查询因子:
WITH cte ( class_id, student, marks, s, m, smax, mmax ) AS (
SELECT class_id,
student,
marks,
1,
1,
REGEXP_COUNT( student, '[^,]+' ),
REGEXP_COUNT( marks, '[^,]+' )
FROM table_name
UNION ALL
SELECT class_id,
student,
marks,
CASE WHEN m = mmax THEN s + 1 ELSE s END,
CASE WHEN m = mmax THEN 1 ELSE m + 1 END,
smax,
mmax
FROM cte
WHERE m < mmax OR s < smax
)
SELECT class_id,
REGEXP_SUBSTR( student, '[^,]+', 1, s ) AS student,
TO_NUMBER( REGEXP_SUBSTR( mark, '[^,]+', 1, m ) ) AS mark
FROM cte;
答案 2 :(得分:0)
使用ora:tokenizer
with t(class_id, student, marks) as (
select 1, 'tom,jam,tim', '55,65,75' from dual union all
select 2, 'rim,gum,ram', '33,66,77' from dual
)
select class_id,new_student,new_marks from t
,xmltable('for $i in ora:tokenize($students,",") return $i' passing student as "students" columns new_student varchar2(20) path '.')
,xmltable('for $j in ora:tokenize($marks,",") return $j' passing marks as "marks" columns new_marks varchar2(20) path '.')
答案 3 :(得分:0)
试试这个
with temp as
(
select 1 class_id , 'tom,jam,tim' student, '55,65,75' marks from dual
union all
select 2 class_id , 'rim,gum,ram' student, '33,66,77' marks from dual
)
select distinct
t.class_id,
trim(regexp_substr(t.student, '[^,]+', 1, students.column_value)) as students,
trim(regexp_substr(t.marks, '[^,]+', 1, marks.column_value)) as marks
from
temp t,
table(cast(multiset(select level from dual connect by level <= length (regexp_replace(t.student, '[^,]+')) + 1) as sys.OdciNumberList)) students,
table(cast(multiset(select level from dual connect by level <= length (regexp_replace(t.marks, '[^,]+')) + 1) as sys.OdciNumberList)) marks
order by class_id;