请仔细阅读,如果您不明白我在说什么,请告诉我。
下面是表名称和这些表中的列
表格:SYSTEM_USER_SKILL
user_id
skill_id
user_abilities
表: SYSTEM_ADMIN_SKILL
skill_id
skill_name
表: SYSTEM_USER
user_id
user_full_name
我想编写一个动态sql或pl/sql来显示user_full_name和user_ability。
但我希望它像这样显示:
附:您可以在其中看到“Y”和“N”,这些是 user_bility 的结果
我不知道如何做到这一点,我只知道它可以使用动态 sql 或 pl/sql 来完成
最佳答案
只要您使用的是 Oracle 11gR2,就可以使用pivot
来获取表格形式的数据:
select * from (
select su.user_full_name, sas.skill_name, sus.user_abilities
from system_user su
cross join system_admin_skill sas
left join system_user_skill sus on sus.user_id = su.user_id
and sus.skill_id = sas.skill_id
) pivot (max(user_abilities) as able for (skill_name)
in ('php' as php, 'java' as java, 'pl/sql / sql' as plsql_sql,
'Oracle apex' as oracle_apex));
USER_FULL_NAME PHP_ABLE JAVA_ABLE PLSQL_SQL_ABLE ORACLE_APEX_ABLE
-------------------- -------- --------- -------------- ----------------
Sarah woods N N Y Y
John brown N Y Y Y
Johnny paterson Y Y Y Y
Amy brown N N Y N
但您需要在 in
子句中明确列出每项技能。 SQL Fiddle .
在 SQL*Plus 或 SQL Developer 中,您可以通过以下方式获得所需的标题:
column user_full_name heading "Name"
column php_able format a15 heading "php"
column java_able format a15 heading "java"
column plsql_sql_able format a15 heading "pl/sql / sql"
column oracle_apex_able format a15 heading "Oracle apex"
select ...
Name php java pl/sql / sql Oracle apex
-------------------- --------------- --------------- --------------- ---------------
Sarah woods N N Y Y
John brown N Y Y Y
Johnny paterson Y Y Y Y
Amy brown N N Y N
...但我不知道 Toad 是否有类似的东西。
与此等效的非枢轴,您必须在旧版本中使用,如下所示:
select su.user_id, su.user_full_name,
max(case when sas.skill_id = 1 then sus.user_abilities end) as php,
max(case when sas.skill_id = 2 then sus.user_abilities end) as java,
max(case when sas.skill_id = 3 then sus.user_abilities end) as plsql_sql,
max(case when sas.skill_id = 4 then sus.user_abilities end) as oracle_apex
from system_user su
cross join system_admin_skill sas
left join system_user_skill sus on sus.user_id = su.user_id
and sus.skill_id = sas.skill_id
group by su.user_id, su.user_full_name;
这仍然具有硬编码的所有技能。为了允许额外的技能而无需修改查询,您需要动态构建它,如评论中链接的早期答案所示。在这种特定情况下,您可以执行以下操作:
create or replace function get_skill_matrix return sys_refcursor as
query varchar2(32767);
rc sys_refcursor;
begin
query := 'select su.user_id, su.user_full_name';
for tmp in (select skill_id, skill_name from system_admin_skill
order by skill_id)
loop
query := query || ', max(case when sas.skill_id = ' || tmp.skill_id
|| ' then sus.user_abilities end) as "'
|| substr(tmp.skill_name, 1, 30) || '"';
end loop;
query := query || ' from system_user su';
query := query || ' cross join system_admin_skill sas';
query := query || ' left join system_user_skill sus on sus.user_id = su.user_id';
query := query || ' and sus.skill_id = sas.skill_id';
query := query || ' group by su.user_id, su.user_full_name';
open rc for query;
return rc;
end;
/
用于动态 SQL 的 query
字符串只是构建为看起来与静态版本完全相同,但每个 skill_id
特定子句是在循环中生成的来自基本 system_admin_skill
表。
当你调用这个函数时,你会得到一个光标。您还没有真正说明如何或在何处使用结果。您可以将其视为 Java 程序中的结果集,例如,通过执行该函数,然后在语句对象上调用 getCursor()
。在 SQL*Plus 或 SQL Developer 中,您可以使用 variable
和 print
命令来显示它:
var rc refcursor;
exec :rc := get_skill_matrix;
print rc
在 SQL Developer 中给出:
anonymous block completed
RC
----------------------------------------------------------------------------------------------
USER_ID USER_FULL_NAME java php pl/sql / sql Oracle apex
--------------------------------------- -------------------- ---- --- ------------ -----------
3 Amy brown N N Y N
4 Sarah woods N N Y Y
2 Johnny paterson Y Y Y Y
1 John brown Y N Y Y
或者在 SQL*Plus 中,您可以执行column user_id noprint
来隐藏 ID(我已经将其包含在内,以防两个人同名!):
Name j p p O
-------------------- - - - -
Amy brown N N Y N
Sarah woods N N Y Y
Johnny paterson Y Y Y Y
John brown Y N Y Y
在 Toad 中,我认为你可以做到这一点,这就是 exec
正在做的所有事情:
开始 :rc := get_skill_matrix; 结束;
...它会提示您输入 :rc
的绑定(bind)类型;如果您选择“引用光标”,它将在数据网格中显示结果。 Apparently .
好的,同样的事情,但没有函数(但仍然是 PL/SQL),并在截断之前将技能 ID 包含在列别名中以使其唯一:
var rc refcursor
declare
query varchar2(32767);
begin
query := 'select su.user_id, su.user_full_name as "Name"';
for tmp in (select skill_id, skill_name from system_admin_skill
order by skill_id) loop
query := query || ', max(case when sas.skill_id = ' || tmp.skill_id
|| ' then sus.user_abilities end) as "'
|| substr(tmp.skill_id || ' ' || tmp.skill_name, 1, 30) || '"';
end loop;
query := query || ' from system_user su';
query := query || ' cross join system_admin_skill sas';
query := query || ' left join system_user_skill sus on sus.user_id = su.user_id';
query := query || ' and sus.skill_id = sas.skill_id';
query := query || ' group by su.user_id, su.user_full_name';
open :rc for query;
end;
/
print rc
这给出:
RC
-----------------------------------------------------------------------------
USER_ID Name 1 java 2 php 3 pl/sql / sql 4 Oracle apex
-------------- -------------------- ------ ----- -------------- -------------
3 Amy brown N N Y N
4 Sarah woods N N Y Y
2 Johnny paterson Y Y Y Y
1 John brown Y N Y Y
关于plsql - 更改 oracle 输出结果的方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21557486/