【问题标题】:changing how oracle output results改变 oracle 输出结果的方式
【发布时间】:2014-02-28 17:13:06
【问题描述】:

请仔细阅读,如果您不明白我在说什么,请告诉我。

下面是表名和这些表中的列

表: 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_abilities 的结果

我不知道该怎么做,我只知道可以用动态 sql 或 pl/sql 来完成

【问题讨论】:

  • 显示在哪里?您是否已经有查询来获取值和组合?你想要输出网格,或者像这样的确切标题(旋转必须留给你......)?您是否拥有固定数量的技能,或者您是否正在尝试找到一种方法来使用动态数量的列进行数据透视?

标签: plsql oracle11g dynamic-sql toad


【解决方案1】:

只要您使用的是 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 中,您可以使用 variableprint 命令来显示它:

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             

【讨论】:

  • 一点补充:如果您转入 XML 然后使用它,您可以轻松处理动态列数量,例如在 Excel 中
  • @Simon - 不确定是否需要动态列,但看起来可能需要。不过,我可能不得不尝试一下;仍然取决于输出将如何被使用或进一步操作。
  • @AlexPoole 非常感谢。我从未听说过 Pivot,我现在有机会学习它。再次感谢
  • 我有一个问题,因为技能名称不仅仅是jusy php。 java等我将避免列出谁?因为将来可能会添加新技能,而且我们在SYSTEM_ADMIN_SKILL 表中有超过 60 种技能
  • @user3057514 - 不那么简单。这就是西蒙的评论所指的,但这取决于你如何使用输出。您还可以构建动态查询as shown herefor example。在添加新值时修改数据透视查询的过程可能会更简单,如果这不会很频繁 - 我想在清晰度和可维护性之间进行权衡。
猜你喜欢
  • 2018-10-06
  • 2010-12-10
  • 1970-01-01
  • 1970-01-01
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多