只要您使用的是 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;
这仍然包含硬编码的所有技能。要允许其他技能而不必修改查询,您需要动态构建它,如之前在 cmets 中链接的答案所示。在这种特定情况下,您可以执行以下操作:
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 的绑定类型;如果您选择“参考光标”,它将在数据网格中显示结果。 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