将日志行转置为 PL/SQL 中的多个列
Transpose log rows to multiple colums in PL/SQL
我的公司 Log_Info 合二为一 table,带有工厂 ID、部门 ID、日志日期、日志小时、日志分钟以及计数器值。请帮助我如何将 [Log hour + Log min] 转换为列,正如我们在这种情况下使用 Oracle 数据库 10g 版本 10.2 中的 PL/SQL 看到的那样。
非常感谢。
我会告诉您使用 PIVOT,这是在本机执行此类操作的一种极其简单的方法,但不幸的是,我相信它是在 11g 中引入的。据我所知,您有两种选择;如果你想保持原生 SQL,你必须使用硬编码的 case 语句。否则,此解决方案可能对您有用..
declare v_str varchar2(2000);
begin
v_str:='select factoryid,deptid,logdate';
for i in (select distinct 'H'||loghour||'_'||logmin a from test_table order by a) loop
v_str:=v_str||',max(case ''H''||loghour||''_''||logmin when '''||i.a||''' then counter end) as "'||i.a||'"';
end loop;
v_str:=v_str||' from test_table group by factoryid,deptid,logdate order by factoryid';
DBMS_OUTPUT.PUT_LINE(v_str);
end;
这将为您提供一个动态查询,然后您可以在循环中或在结果集中执行该查询,无论您选择什么(而不是我这里的 PUT_LINE)。根据您提供的当前数据,此块的结果是:
select factoryid,deptid,logdate,
max(case 'H'||loghour||'_'||logmin when 'H0_0' then counter end) as "H0_0",
max(case 'H'||loghour||'_'||logmin when 'H0_30' then counter end) as "H0_30",
max(case 'H'||loghour||'_'||logmin when 'H1_0' then counter end) as "H1_0",
max(case 'H'||loghour||'_'||logmin when 'H1_30' then counter end) as "H1_30",
max(case 'H'||loghour||'_'||logmin when 'H2_0' then counter end) as "H2_0"
from test_table
group by factoryid,deptid,logdate order by factoryid
这将为您提供您正在寻找的东西。
编辑:请注意,包含 MAX 是为了消除 case 语句中的所有内容,使其不在 group by 中。这是假设每个工厂每次只有一个计数器值 id/deptid/logdate。
如果您想走原生路线并定义 loghour 和 logmin 列表(不是 100% 确定,但看起来您将从 H0_0 转到 H23_30 ),您可以使用上面吐出的 PL/SQL 块查询,并继续创建 case 语句,直到所有 loghours 和 logmins 都被考虑在内。如果是这种情况并且 loghour/min 具有定义的跨度,您应该这样做,因为使用本机 SQL 而不是动态 SQL.[=12 具有性能优势,例如游标缓存=]
我的公司 Log_Info 合二为一 table,带有工厂 ID、部门 ID、日志日期、日志小时、日志分钟以及计数器值。请帮助我如何将 [Log hour + Log min] 转换为列,正如我们在这种情况下使用 Oracle 数据库 10g 版本 10.2 中的 PL/SQL 看到的那样。
非常感谢。
我会告诉您使用 PIVOT,这是在本机执行此类操作的一种极其简单的方法,但不幸的是,我相信它是在 11g 中引入的。据我所知,您有两种选择;如果你想保持原生 SQL,你必须使用硬编码的 case 语句。否则,此解决方案可能对您有用..
declare v_str varchar2(2000);
begin
v_str:='select factoryid,deptid,logdate';
for i in (select distinct 'H'||loghour||'_'||logmin a from test_table order by a) loop
v_str:=v_str||',max(case ''H''||loghour||''_''||logmin when '''||i.a||''' then counter end) as "'||i.a||'"';
end loop;
v_str:=v_str||' from test_table group by factoryid,deptid,logdate order by factoryid';
DBMS_OUTPUT.PUT_LINE(v_str);
end;
这将为您提供一个动态查询,然后您可以在循环中或在结果集中执行该查询,无论您选择什么(而不是我这里的 PUT_LINE)。根据您提供的当前数据,此块的结果是:
select factoryid,deptid,logdate,
max(case 'H'||loghour||'_'||logmin when 'H0_0' then counter end) as "H0_0",
max(case 'H'||loghour||'_'||logmin when 'H0_30' then counter end) as "H0_30",
max(case 'H'||loghour||'_'||logmin when 'H1_0' then counter end) as "H1_0",
max(case 'H'||loghour||'_'||logmin when 'H1_30' then counter end) as "H1_30",
max(case 'H'||loghour||'_'||logmin when 'H2_0' then counter end) as "H2_0"
from test_table
group by factoryid,deptid,logdate order by factoryid
这将为您提供您正在寻找的东西。
编辑:请注意,包含 MAX 是为了消除 case 语句中的所有内容,使其不在 group by 中。这是假设每个工厂每次只有一个计数器值 id/deptid/logdate。
如果您想走原生路线并定义 loghour 和 logmin 列表(不是 100% 确定,但看起来您将从 H0_0 转到 H23_30 ),您可以使用上面吐出的 PL/SQL 块查询,并继续创建 case 语句,直到所有 loghours 和 logmins 都被考虑在内。如果是这种情况并且 loghour/min 具有定义的跨度,您应该这样做,因为使用本机 SQL 而不是动态 SQL.[=12 具有性能优势,例如游标缓存=]