一、需求
有一張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;