作为一名真正的学生,我在昨晚的课程中工作:) 但我试着写了几天这个查询,我不知道该怎么做。这就是为什么我在这里写作的原因。
很抱歉这可能是一个愚蠢的问题,但是我们所有人都在前一段时间里做了很多错误和问题的编程。 (抱歉我的英语,它现在很完美)。
顺便说一下,我的任务是:
我们有3个表格(地区,城市和实验[名为'数据'])。第三个表格(实验['数据'])有so2_d字段(特定日期在空中的内容为so2)。
我需要创建一份报告,了解每个城市空气中最大的内容分布情况,使用特定年份的季度(确切地说并不重要)。 即,该表必须如下所示:
这意味着我们需要通过水平和垂直方式来总结。
我尝试用1个光标,2个光标做它...它没有用。在大多数情况下,我遇到了这个错误:so2是不明确的。
这是我的代码示例。 (我知道它很糟糕但没有结束,但我希望你能理解......):
CREATE OR REPLACE FUNCTION so2_report()
RETURNS text AS
$$
DECLARE
name_r regions.name_r %TYPE; name_c cities.name_c %TYPE;
quarter_1 data.so2_d %TYPE := 0; quarter_2 data.so2_d %TYPE := 0; quarter_3 data.so2_d %TYPE := 0; quarter_4 data.so2_d %TYPE := 0;
quarter INTEGER; counter INTEGER := 0;
string TEXT;
cursor1 CURSOR FOR
SELECT regions.name_r, cities.name_c FROM regions INNER JOIN cities USING (id_r) INNER JOIN data USING (id_c);
cursor2 CURSOR FOR
SELECT max(data.so2_d) FROM data WHERE EXTRACT(QUARTER FROM date_d) = quarter AND data.id_c = counter;
BEGIN
string := repeat(' ', 90) || 'Report' || E'\n';
string := string || repeat(' ', 65) || 'about maximum so2 content in air' || E'\n\n';
string := string || repeat(' ', 5) || 'Region' || repeat(' ', 15) || 'City' || repeat(' ', 25) || 'I quarter' || repeat(' ', 10) ||
'ІІ quarter' || repeat(' ', 10) || 'ІІІ quarter' || repeat(' ', 10) || 'IV quarter' || repeat(' ', 10) || 'All Year' || E'\n\n';
OPEN cursor1;
LOOP
FETCH next FROM cursor1 INTO name_r, name_c;
exit when not found;
string := string || rpad(name_r, 25) || rpad(name_c, 25);
OPEN cursor2;
counter := counter + 1;
quarter := 0;
LOOP
quarter := quarter + 1;
FETCH next FROM cursor2 INTO quarter_1, quarter_2, quarter_3, quarter_4;
exit when not found;
string := string || rpad(TO_CHAR(quarter_1, '999.99'), 20) ||
rpad(TO_CHAR(quarter_2, '999.99'), 20) || rpad(TO_CHAR(quarter_3, '999.99'), 20) || rpad(TO_CHAR(quarter_4, '999.99'), 20) || E'\n';
END LOOP;
CLOSE cursor2;
END LOOP;
CLOSE cursor1;
RETURN string;
END
$$
LANGUAGE 'plpgsql';
SELECT so2_report();
I will be grateful for any help.
GUYS,我已经解决了!在这里你得到了代码:
CREATE OR REPLACE FUNCTION s_report()
RETURNS text AS
$$
DECLARE
name_r regions.name_r %TYPE; name_c cities.name_c %TYPE;
quarter_1 data.so2_d %TYPE; quarter_2 data.so2_d %TYPE; quarter_3 data.so2_d %TYPE; quarter_4 data.so2_d %TYPE;
year REAL; sum REAL ARRAY[5];
string TEXT;
cursor1 CURSOR FOR
SELECT regions.name_r, cities.name_c,
max( CASE WHEN EXTRACT(QUARTER FROM date_d) = 1 AND EXTRACT(YEAR FROM date_d) = EXTRACT(YEAR FROM current_date) THEN so2_d ELSE 0 END ) As Quarter_1,
max( CASE WHEN EXTRACT(QUARTER FROM date_d) = 2 AND EXTRACT(YEAR FROM date_d) = EXTRACT(YEAR FROM current_date) THEN so2_d ELSE 0 END ) As Quarter_2,
max( CASE WHEN EXTRACT(QUARTER FROM date_d) = 3 AND EXTRACT(YEAR FROM date_d) = EXTRACT(YEAR FROM current_date) THEN so2_d ELSE 0 END ) As Quarter_3,
max( CASE WHEN EXTRACT(QUARTER FROM date_d) = 4 AND EXTRACT(YEAR FROM date_d) = EXTRACT(YEAR FROM current_date) THEN so2_d ELSE 0 END ) As Quarter_4
FROM regions INNER JOIN cities USING (id_r) INNER JOIN data USING (id_c) GROUP BY regions.name_r, cities.name_c;
BEGIN
-- формуємо назву звіту
string := repeat(' ', 50) || 'Звіт' || E'\n';
string := string || repeat(' ', 27) || 'про розподіл максимальних значень SO2 в повітрі' || E'\n\n';
-- формуємо рядок заголовку звіту
string := string || repeat(' ', 5) || 'Область' || repeat(' ', 15) || 'Місто' || repeat(' ', 10) || 'I квартал' || repeat(' ', 5) ||
'ІІ квартал' || repeat(' ', 5) || 'ІІІ квартал' || repeat(' ', 5) || 'IV квартал' || repeat(' ', 5) || 'Рік' || E'\n\n';
--вперед
sum[1] := 0; sum[2] := 0; sum[3] := 0; sum[4] := 0; sum[5] := 0;
--відкриваємо курсор
OPEN cursor1;
LOOP
--витягаємо значення з курсору
FETCH next FROM cursor1 INTO name_r, name_c, quarter_1, quarter_2, quarter_3, quarter_4;
exit when not found;
year := 0;
year := quarter_1 + quarter_2 + quarter_3 + quarter_4;
sum[1] := sum[1] + quarter_1;
sum[2] := sum[2] + quarter_2;
sum[3] := sum[3] + quarter_3;
sum[4] := sum[4] + quarter_4;
sum[5] := sum[5] + year;
string := string || rpad(name_r, 25) || rpad(name_c, 16) || rpad(TO_CHAR(quarter_1, '999.99'), 16) || rpad(TO_CHAR(quarter_2, '999.99'), 14) ||
rpad(TO_CHAR(quarter_3, '999.99'), 15) || rpad(TO_CHAR(quarter_4, '999.99'), 12) || TO_CHAR(year, '999.99') || E'\n';
END LOOP;
CLOSE cursor1;
string := string || E'\n' || repeat(' ', 11) || rpad('Всього', 30) || rpad(TO_CHAR(sum[1], '999.99'), 16) || rpad(TO_CHAR(sum[2], '999.99'), 14) ||
rpad(TO_CHAR(sum[3], '999.99'), 15) || rpad(TO_CHAR(sum[4], '999.99'), 12) || TO_CHAR(sum[5], '999.99');
RETURN string;
END
$$
LANGUAGE 'plpgsql';
SELECT s_report();
答案 0 :(得分:0)
尽量避免使用程序代码。
您正在使用SQL - 最美丽的声明性语言之一。
如果我从您的代码中正确地猜测您的要求和表格结构,下面的简单SQL语句应该会给您一个非常接近您要求的结果:
SELECT regions.name_r, cities.name_c,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 1 THEN so2_d END ) As Quarter_1,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 2 THEN so2_d END ) As Quarter_2,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 3 THEN so2_d END ) As Quarter_3,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 4 THEN so2_d END ) As Quarter_4
FROM regions
INNER JOIN cities USING (id_r)
INNER JOIN data USING (id_c)
GROUP BY regions.name_r, cities.name_c
;
缺失的部分是每个季度的最终总和,以及每年的总和和最终总数
这个查询应该很容易实现(未经测试):
WITH dd As(
SELECT regions.name_r, cities.name_c,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 1 THEN so2_d END ) As Quarter_1,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 2 THEN so2_d END ) As Quarter_2,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 3 THEN so2_d END ) As Quarter_3,
avg( CASE WHEN EXTRACT(QUARTER FROM date_d) = 4 THEN so2_d END ) As Quarter_4
FROM regions
INNER JOIN cities USING (id_r)
INNER JOIN data USING (id_c)
GROUP BY regions.name_r, cities.name_c
)
SELECT dd.*,
Quarter_1 + Quarter_2 + Quarter_3 + Quarter_4 As All_year
FROM dd
UNION All
SELECT 'TOTAL', NULL,
SUM( Quarter_1 ),
SUM( Quarter_2 ),
SUM( Quarter_3 ),
SUM( Quarter_4 ),
SUM( Quarter_1 + Quarter_2 + Quarter_3 + Quarter_4 )
FROM dd
;