一、需求
有一张news表记录平台每天所有文章的点击情况,字段有
CREATE_TIME
是该文章创建的时间。
每天跑前一天的数据,要求创建时间范围从去年对日到今年当天的所有文章在当天PV和
select DATE_ID,SUM(PV) FROM NEWS
WHERE DATE_ID=TO_CHAR(SYSDATE-1, 'YYYYMMDD')
AND TO_CHAR(CREATE_TIME,'YYYYMMDD') BETWEEN TO_CHAR(add_months(SYSDATE-1,-12), 'YYYYMMDD') AND TO_CHAR(SYSDATE-1, 'YYYYMMDD')
GROUP BY DATE_ID
每一天要合计的pv值,CREATE_TIME区间都不一致。
如果需要前一天的数据,机械的办法是则把SYSDATE-1改成SYSDATE-2运行一遍,需要前多少天则要重新跑多少遍数据。
- 可以使用以下语句,内部循环,取出多日的定区合计数据,这种速度也相对较快
select DATE_ID,SUM(PV) FROM NEWS
WHERE DATE_ID>=TO_CHAR(SYSDATE-3, 'YYYYMMDD')
AND TO_CHAR(CREATE_TIME,'YYYYMMDD') BETWEEN TO_CHAR(add_months(to_date(DATE_ID,'yyyymmdd'),-12), 'YYYYMMDD') AND TO_CHAR(to_date(DATE_ID,'yyyymmdd'), 'YYYYMMDD')
GROUP BY DATE_ID
ORDER BY 1
- 现在使用PLSQL里面的循环语句实现一次性输出前3天的数据,该种方法实际上是将语句运行了3次,速度相对较慢。
二、实现
1、基本循环
DECLARE
v_n INT:=3;--定义控制参数
v_date NEWS.DATE_ID%TYPE;--定义要输出的变量
v_pvs NEWS.PV%TYPE;--定义要输出的变量
BEGIN
LOOP
select DATE_ID,SUM(PV) INTO v_date,v_pvs
FROM NEWS
WHERE DATE_ID=TO_CHAR(SYSDATE-v_n, 'YYYYMMDD')
AND TO_CHAR(CREATE_TIME,'YYYYMMDD') BETWEEN TO_CHAR(add_months(SYSDATE-v_n,-12), 'YYYYMMDD') AND TO_CHAR(SYSDATE-v_n, 'YYYYMMDD')
GROUP BY DATE_ID;
DBMS_OUTPUT.PUT_LINE(v_date||' '||v_pvs);
v_n:=v_n-1;--参数自减
EXIT WHEN v_n<1;--退出条件
END LOOP;
END;
2、while 循环
DECLARE
v_n INT:=3;--定义控制参数
v_date NEWS.DATE_ID%TYPE;--定义要输出的变量
v_pvs NEWS.PV%TYPE;-- 定义要输出的变量
BEGIN
WHILE v_n>=1 LOOP--循环条件
select DATE_ID,SUM(PV) INTO v_date,v_pvs
FROM NEWS
WHERE DATE_ID=TO_CHAR(SYSDATE-v_n, 'YYYYMMDD')
AND TO_CHAR(CREATE_TIME,'YYYYMMDD') BETWEEN TO_CHAR(add_months(SYSDATE-v_n,-12), 'YYYYMMDD') AND TO_CHAR(SYSDATE-v_n, 'YYYYMMDD')
GROUP BY DATE_ID;
DBMS_OUTPUT.PUT_LINE(v_date||' '||v_pvs);
v_n:=v_n-1; --参数自减
END LOOP;
END;
3、For 循环
DECLARE
v_date NEWS.DATE_ID%TYPE;
v_pvs NEWS.PV%TYPE;
BEGIN
FOR v_n IN REVERSE 1..3 LOOP--默认定义控制参数
select DATE_ID,SUM(PV) INTO v_date,v_pvs
FROM NEWS
WHERE DATE_ID=TO_CHAR(SYSDATE-v_n, 'YYYYMMDD')
AND TO_CHAR(CREATE_TIME,'YYYYMMDD') BETWEEN TO_CHAR(add_months(SYSDATE-v_n,-12), 'YYYYMMDD') AND TO_CHAR(SYSDATE-v_n, 'YYYYMMDD')
GROUP BY DATE_ID;
DBMS_OUTPUT.PUT_LINE(v_date||' '||v_pvs);
END LOOP;
END;