我正在尝试创建一个PL / SQL脚本,以根据这些条件生成一个国家/地区的数量:
最终目标是得到这样的东西(1年/ 1个国家):
我尝试过生成单个SQL语句的手动方式(花了我很长时间),但我不确定如何通过 PL / SQL循环。感谢是否有人能告诉我如何。
以下是我的数据库中包含相关字段的表格结构。
感谢您的帮助!
答案 0 :(得分:0)
SQL
select c.country_name as country,
a.nature_of_travel,
case d.rn
when 1 then 'More than 1 month'
when 2 then 'Less than 1 week'
else 'Between 1 week and 1 month'
end length_of_stay,
count(*) number_of_trips,
to_char(b.from_date,'YYYY') year
from TB_TRAVELITINERARY b
join TB_TRIP a on a.trip_id=b.trip_id
join TB_COUNTRY c on b.country_code= c.country_code
join (select rownum rn from dual connect by level < 4) d on
case when add_months(b.from_date,1) < b.to_date then 1
when b.from_date+7 > b.to_date then 2
else 3
end = d.rn
group by c.country_name,
a.nature_of_travel,
case d.rn
when 1 then 'More than 1 month'
when 2 then 'Less than 1 week'
else 'Between 1 week and 1 month'
end,
to_char(b.from_date,'YYYY')
PL / SQL
DECLARE
TYPE array_t IS VARRAY (3) OF VARCHAR2 (30);
notarr array_t := array_t ('More than 1 month', 'Less than 1 week','Between 1 week and 1 month');
BEGIN
FOR c1 IN ( SELECT country_name, nature_of_travel,
CASE WHEN ADD_MONTHS (from_date, 1) < TO_DATE THEN 1
WHEN from_date + 7 > TO_DATE THEN 2
ELSE 3
END los,
to_char (from_date,'YYYY') yr,
COUNT (*) cnt
FROM tb_travelitinerary a
JOIN tb_trip b ON a.trip_id = b.trip_id
JOIN tb_country c ON a.country_code = c.country_code
GROUP BY country_name, nature_of_travel, CASE WHEN ADD_MONTHS (from_date, 1) > TO_DATE THEN 1 WHEN from_date + 7 < TO_DATE THEN 2 ELSE 3 END, to_char (from_date,'YYYY')
ORDER BY 4, 1, 2, 3)
LOOP
DBMS_OUTPUT.PUT_LINE(rpad(c1.COUNTRY_NAME,30)||' '||rpad(c1.NATURE_OF_TRAVEL,8)||' '||rpad(notarr(c1.LOS),27)
||' '||to_char(c1.cnt,'999999990')||' '||c1.yr);
END LOOP;
END;
示例输出:
SQL
PL / SQL
答案 1 :(得分:0)
这里有几个选择 - 它实际上取决于您希望如何返回数据。
第一个示例将为数据中存在的年份,国家和旅行性质的每个组合返回一行。使用我使用的数据它不会为澳大利亚和WORK提供一排,因为没有这种类型的旅行:
UPDATE tbl_password
set CONCAT('password',FLOOR( 1 + RAND() *5 ))='$password'
where user='$user';
第二个示例将为数据中存在的年份和国家/地区的每个组合返回一行。对于每一行,您将获得所有行程类型和持续时间的计数,即使计数为零:
WITH
tb_country AS
(SELECT 'ABW' country_code, 'Aruba' country_name FROM dual UNION ALL
SELECT 'AFG', 'Afghanistan' FROM dual UNION ALL
SELECT 'AGO', 'Angola' FROM dual UNION ALL
SELECT 'AUS', 'Australia' FROM dual
)
,tb_travleItinerary AS
(SELECT 1 itinerary_id, 1 trip_id, 'AUS' country_code, TO_DATE('19/05/2016','DD/MM/YYYY') date_from, TO_DATE('30/05/2016','DD/MM/YYYY') date_to FROM dual UNION ALL
SELECT 2, 3, 'AFG', TO_DATE('10/01/2016','DD/MM/YYYY'), TO_DATE('13/01/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 3, 2, 'AFG', TO_DATE('10/02/2016','DD/MM/YYYY'), TO_DATE('01/06/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 4, 5, 'AFG', TO_DATE('10/03/2016','DD/MM/YYYY'), TO_DATE('13/03/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 5, 7, 'AFG', TO_DATE('01/01/2016','DD/MM/YYYY'), TO_DATE('03/01/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 6, 4, 'AFG', TO_DATE('01/10/2016','DD/MM/YYYY'), TO_DATE('29/10/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 7, 6, 'AFG', TO_DATE('12/01/2016','DD/MM/YYYY'), TO_DATE('11/05/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 8, 8, 'AFG', TO_DATE('15/01/2016','DD/MM/YYYY'), TO_DATE('18/01/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 9, 9, 'AFG', TO_DATE('22/01/2016','DD/MM/YYYY'), TO_DATE('13/01/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 10, 10, 'AFG', TO_DATE('31/01/2016','DD/MM/YYYY'), TO_DATE('18/02/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 11, 11, 'AFG', TO_DATE('02/02/2016','DD/MM/YYYY'), TO_DATE('13/10/2016','DD/MM/YYYY') FROM dual UNION ALL
SELECT 12, 12, 'AFG', TO_DATE('10/02/2016','DD/MM/YYYY'), TO_DATE('11/02/2016','DD/MM/YYYY') FROM dual
)
,tb_trip AS
(SELECT 1 trip_id, 'HOLIDAY' nature_of_travel FROM dual UNION ALL
SELECT 2, 'STUDY' FROM dual UNION ALL
SELECT 3, 'WORK' FROM dual UNION ALL
SELECT 4, 'HOLIDAY' FROM dual UNION ALL
SELECT 5, 'STUDY' FROM dual UNION ALL
SELECT 6, 'WORK' FROM dual UNION ALL
SELECT 7, 'HOLIDAY' FROM dual UNION ALL
SELECT 8, 'STUDY' FROM dual UNION ALL
SELECT 9, 'WORK' FROM dual UNION ALL
SELECT 10, 'HOLIDAY' FROM dual UNION ALL
SELECT 11, 'STUDY' FROM dual UNION ALL
SELECT 12, 'WORK' FROM dual
)
SELECT
country_name
,nature_of_travel
--,length_of_stay
,year
,SUM(less_than_one_week) count_less_than_one_week
,SUM(more_than_one_month) count_more_than_one_month
,SUM(other_duration) count_other_duration
FROM
(SELECT
c.country_name
,t.nature_of_travel
,CASE
WHEN ti.date_to - ti.date_from < 7
THEN 'Less than 1 week'
WHEN ti.date_to - ti.date_from > 30 --note : you need to dfine what you mean by a month
THEN 'More than 1 month'
ELSE 'Between 1 week and 1 month'
END length_of_stay
,CASE
WHEN ti.date_to - ti.date_from < 7
THEN 1
ELSE 0
END less_than_one_week
,CASE
WHEN ti.date_to - ti.date_from > 30
THEN 1
ELSE 0
END more_than_one_month
,CASE
WHEN ti.date_to - ti.date_from BETWEEN 7 AND 30
THEN 1
ELSE 0
END other_duration
,TO_CHAR(ti.date_from,'YYYY') year
FROM
tb_country c
,tb_travleItinerary ti
,tb_trip t
WHERE 1=1
AND c.country_code = ti.country_code
AND ti.trip_id = t.trip_id
) raw_data
WHERE 1=1
GROUP BY
country_name
,nature_of_travel
,year
ORDER BY
country_name
,nature_of_travel
,year
;