尝试使用PL / SQL WHILE LOOP来处理变量

时间:2014-09-04 19:10:06

标签: sql oracle

我正在努力让它在Oracle SQL Developer中运行。

我想开始一个查询,然后在它的前几行之后运行一个while循环来循环几周。我还没有完整地解决整个问题,因为我甚至无法弄清楚如何使用这样的WHILE LOOP。

这是一个简单的例子,我知道我需要指定一些日期字段等,但希望你能得到我想要的东西。基本上尝试为每周的交易创建一个新列。默认的Oracle WW或IW值对我们不起作用。

我知道在这个查询中有很多其他的调整需要理顺,不太确定逗号应该在哪里而不是。我不习惯在SQL Developer中工作来完成这些任务。感谢您的任何反馈!

DECLARE
MyDayVar  VARCHAR2(20) := '05-JAN-14'; --sets the start of Week2
MyWeekVar VARCHAR2(20) := '2';
SELECT Customer_Name, 
sum(CASE when PLANNED_SHIP_DATE >= '01-JAN-14' and PLANNED_SHIP_DATE <= '04-JAN-14' then (REVISED_QTY_DUE - QTY_SHIPPED) * SALE_UNIT_PRICE end) as Wk1 --trying to get Week 1 of 2014,

WHILE 
MyDayVar =< '01-JAN-15'
LOOP

sum(CASE when PLANNED_SHIP_DATE >= :MyDayVar and PLANNED_SHIP_DATE <= (:MyDayVar + 7) then (REVISED_QTY_DUE - QTY_SHIPPED) * SALE_UNIT_PRICE end) as Wk + :MyWeekVar --trying to get Week 2 of 2014 and display as 'Wk2',
MyDayVar = :MyDayVar + 7; --add 7 days to MyDayVar to prepare for the next day;
MyWeekVar = :MyWeekVar + 1; --add 1 to the Week Variabkle;
FROM CUSTOM_ORDERS_TABLE
WHERE PLANNED_SHIP_DATE => '01-JAN-14' --only grab year 2014 data
END LOOP

1 个答案:

答案 0 :(得分:0)

让我们首先重新陈述您的问题,以明确您的实际目标:您希望汇总一年中每周的已发货订单的价值。

您对周的定义&#39;是七天盯着周日。 S,o除非1月1日是星期日,否则你的第一周将会很短。据推测,此要求是您无法使用Oracle IW或WW格式掩码生成每周存储桶的原因。幸运的是,Oracle还有其他有用的日期操作,可以帮助解决这个问题。

我们可以在带有格式掩码的日期上使用trunc()来获取特定值。所以trunc(sysdate, 'yyyy')给了我们今年的第一天。我们可以硬编码01-JAN-2014,但为什么不更灵活?无论如何,find out more

我们可以使用next_day()向我们提供指定日期的下一个日期。所以next_date(sysdate, 'SUN')给了我们下个星期天。请注意,如果今天是星期日,它将为我们提供 next 星期日的日期。 Find out more

我们在日期使用算术运算。因此sysdate+7为我们提供了下周这一天的日期。

另一个有用的构造是子查询因子,AKA是with子句。旨在提高在查询中出现多次的子查询的效率,它还提供了一种生成数据集的方法。 Find out more。在下面的PoC代码中,我使用Oracle的hierarchical query construct来生成一年中所有星期日的集合。

因此,使用所有这些工具,我们可以在单个查询中解决您的问题,而无需使用PL / SQL:

with yr as ( select next_day(trunc(sysdate,'yyyy')-1, 'SUN') as first_sunday
              from dual )
     , sundays as ( select first_sunday + ((level-1)*7) as this_sunday
                         , first_sunday + ((level-2)*7) as prev_sunday
                 from yr
                 connect by level <= 53 ) 
select sundays.this_sunday as sunday
       , sum ( case when t.planned_ship_date >= sundays.prev_sunday
                       and t.planned_ship_date < sundays.this_sunday
                  then ((t.revised_qty_due - t.qty_shipped) * t.sale_unit_price)
                  else 0 end ) as wk_total
from sundays
     cross join custom_orders_table t
where t.planned_ship_date between date '2014-01-01' and date '2014-12-31'
group by sundays.this_sunday
order by sundays.this_sunday

SQL Fiddle有一个简化的问题版本。 Check it out