我是一名报告撰稿人。我的查询通常来自某些来源的SELECT语句(在本例中为Oracle Exadata),它从WHERE中的一个或多个表,连接,过滤器中选择,进一步过滤HAVING中的组等。我通常只拥有对任何来源的READ权限。 ; m连接到。所以,我无法创建sprocs,包或函数。
我需要在复杂查询上使用高级功能,使用FOR..LOOPs,IF THEN ELSE结构等来优化派生结果集,以便输出到报告工具(如Qlikview或Tableau)。
随着我的学习,我在复杂的逻辑结构中找到了许多使用游标的课程,但每节课都使用dbms_output.put_line作为每次迭代的结果。输出最终在缓冲区中,而不是结果集。我已经了解到SYS_REFCURSOR是指向结果集的指针。听起来很有希望,但所有例子都以创建或替换程序/包装开始。
我的理解存在差距,如果我解释了我期望的结果,我希望你能填补这些空白:
我有一个复杂的查询,它通过UNION合成多个SELECT语句,在Join和Where子句中使用子选择等。它返回一个几乎完整的结果集,但我需要在发送之前进一步完善它结果设置为报告工具。
我可以:
DECLARE
CURSOR current_Schedule IS
SELECT --insert complex query here-- ;
row_Schedule cur_Schedule%ROWTYPE;
BEGIN
IF NOT current_Schedule%ISOPEN THEN
OPEN current_Schedule;
END IF;
LOOP
FETCH current_Schedule INTO row_Schedule;
EXIT WHEN current_Schedule%NOTFOUND;
--Here's where I think my question is....
dbms_output.put_line('row_Schedule.Login ' || row_Schedule.Code)
END LOOP;
EXCEPTION --put exception clause here
END;
这可以验证我可以迭代复杂查询,更新,过滤等结果的概念,但问题是......
它输出到缓冲区,而不是结果集。
我可能误解了一些PL / SQL概念。我在这里找到的所有研究实例和其他来源都假设用户能够创建函数,包等。
我仅限于将此作为脚本从具有源的只读权限的QlikView ODBC连接启动。
考虑到我的限制,是否有解决方案?
感谢您花时间阅读本文,并感谢您能否提供一致的答案。
MFC
编辑:附加信息
我正在使用劳动力管理模式,进行非规范化并将其存放在Exadata数据湖中。我有2个表DET_SEG(详细段)和GEN_SEG(通用段)。 DET_SEG包含员工和段代码表,NOM_DATE,START MOMENT和STOP MOMENT的fk&#39。代码有两种类型,Additive和Subtractive。添加剂是指示员工被分配到的业务单位的工作代码,减法代码是雇员从工作中获取的任何类型的代码,例如Break,Lunch,Sick等。所有代码都绑定到在30分钟生成时间间隔的表。由于代码可能占用一个完整或部分间隔,并且因为它们可以跨越多个间隔,我最终得到了6个独特的用例来解决:以前开始的代码,占用整个并且在后续Interval中结束是一个。之前开始,结束的代码是另一个。 你可以想象其余的,我不会迭代它们。最终输出生成一个标题为" Minutes"表示添加或减法代码在区间中占用的时间。
我最终创建了6个独特的SELECT块UNION,以输出倒数第二个解决方案。这是一个较短的SELECT的例子:
SELECT
cal.GlobalIntervals AS G_Intervals,
mainstart.startmoment AS StartMoment,
mainstart.stopmoment AS StopMoment,
mainstart.code as Code,
mainstart.ID AS Login,
((case mainstart.code
when 'BRK1' then round(24*60*(mainstart.startmoment -mainstart.stopmoment),0)
when 'BRK2' then round(24*60*(mainstart.startmoment - mainstart.stopmoment),0)
when 'BRK3' then round(24*60*(mainstart.startmoment - mainstart.stopmoment),0)
else round(24*60*(mainstart.startmoment - mainstart.stopmoment),0)
end)) as Minutes
from
(
SELECT
(
to_date(to_char((
SELECT CLNDR_DT
FROM COMMOBJ.DIM_DATE
where CLNDR_DT = trunc(sysdate)
), 'dd-mon-yyyy') || HOUR_24_LABEL_CD, 'dd-mon-yyyy hh24:mi:ss')
) as GlobalIntervals
FROM COMMOBJ.DIM_TIME t
WHERE second_nbr = 0
AND mod(minute_nbr, 30) = 0
) cal
left outer join
(
SELECT DISTINCT
New_time(to_date(30121899,'ddMMyyyy')+EWFM.DET_SEG.START_MOMENT/1440,'GMT','PST') as StartMoment,
New_time(to_date(30121899,'ddMMyyyy')+EWFM.DET_SEG.STOP_MOMENT/1440,'GMT','PST') as StopMoment,
SEG_CODE.CODE,
SEG_CODE.DESCR,
EMP.ID,
EMP.LAST_NAME,
EMP.FIRST_NAME
FROM EWFM.DET_SEG DET_SEG
INNER JOIN EWFM.SEG_CODE SEG_CODE ON (DET_SEG.SEG_CODE_SK = SEG_CODE.SEG_CODE_SK)
INNER JOIN EWFM.EMP EMP ON (DET_SEG.EMP_SK = EMP.EMP_SK)
INNER JOIN SBCG_ADHOC.SBCG_STAFF SBCG_STAFF ON (EMP.ID = SBCG_STAFF.AGENT_LOGIN)
WHERE trunc (New_time(to_date(30121899,'ddMMyyyy')+EWFM.DET_SEG.START_MOMENT/1440,'GMT','PST')) = trunc(sysdate)
and EWFM.SEG_CODE.CRNT_REC_IND = 'Y'
and SEG_CODE.CODE NOT IN ('SHIFT', 'CCBOUT', 'HOLIDA', 'LIND', 'PCHT', 'PIND', 'PXTR', 'LCHT', 'LXTR', 'PSVC', 'HV Saves Inbound' )
)mainstart
--StartMoment occurs AFTER Current Interval
on cal.GlobalIntervals < mainstart.StartMoment
--StopMoment occurs on Next Interval
and (cal.GlobalIntervals + (1/24/60 * 30)) = mainstart.StopMoment
--StartMoment occurs prior to Next Interval
and mainstart.StartMoment < (cal.GlobalIntervals + (1/24/60 * 30))
输出如下:
G_INTERVALS | STARTMOMENT | STOPMOMENT |代码|登录| MINUTES
4/17/17 12:00 | 2/17/17 12:00 | 2/17/17 12:15 | BRK1 | ABC123 | -15
4/17/17 12:00 | 2/17/17 12:00 | 2/17/17 08:00 | SHIFT | XYZ321 | 30个
4/17/17 12:30 | 2/17/17 12:45 | 2/17/17 01:45 |午餐| LK4567 | -15
Minutes列的Case语句随每个Use Case的变化以及最终Join中的ON条件而变化。虽然可能不是最有效的,但它会生成一个几乎可以用于收缩报告的数据集。
最终条件(以及此帖子的原因)是GEN_SEG表。它包含Day Long事件的信息,例如Planned Sick(SICKPL),unplanned Sick(SICKUP)等。它只有一个日期,没有START或STOP时刻。这是我正在寻找进一步改进的地方。使用Cursor迭代Result-Set和GEN_SEG中找到的每个Login,并且对于每个值&lt; 0,将其更改为0,以便将与减法代码关联的负值清零。
最终,我们希望在劳动力中发现收缩。员工安排只是第一步。一旦计划内和计划外缩减的员工时间表得到改进,我将引入实际值进一步细化。
我怀疑我写过一本简短的小说,但我希望我已经包含了足够的细节来解释是否需要进行二级细化。如果您有任何想法或批评,我很感激。
干杯〜!
答案 0 :(得分:0)
在PL / SQL块中,您正在使用光标,因此没有任何内容可以返回给客户端。
如果您使用的是Oracle 12c,则可以从匿名块返回游标(请参阅implicit result sets),但是您将返回SQL而无需程序控制。
你可能想要的是pipelined function,它实际上为你提供了程序性视图。但是,您无法从只读帐户执行此操作,因为您需要创建函数及其返回的集合类型。
你可以用SQL做很多事情。我有兴趣知道哪些报告要求需要程序逻辑。