问题更新查询 – 我没有得到我想要的结果。

huangapple go评论81阅读模式
英文:

Problem with update query - I don't get the results I want

问题

I understand your request. Here's the translated code:

我负责一个大学的数据库,我需要更新一个名为register的表的几个列,这些列的名称分别是exam_gradelab_grade和final_gradefinal_grade是基于exam_grade和lab_grade的结果计算的,但是当lab_grade的结果为NULL时final_grade的结果不应该直接等于exam_grade,而应该保持为NULL。以下是该函数的代码:

```sql
DROP FUNCTION public.fn_question_2_2(integer);

CREATE OR REPLACE FUNCTION public.fn_question_2_2(num integer)
RETURNS void
AS
$$
DECLARE
       pointer record;
       percentage numeric;
       exam_i numeric;
       lab_i numeric;
BEGIN
     FOR pointer IN
                   (SELECT rg.amka, rg.lab_grade, rg.exam_grade,
                           rg.serial_number, rg.register_status, 
                           cr.course_code, cr.lab_hours
                    FROM "Register" rg
                    JOIN (SELECT course_code, lab_hours FROM "Course") cr USING (course_code)
                    WHERE rg.register_status = 'approved' AND rg.serial_number = num)
                    LOOP
                        IF (pointer.exam_grade IS NULL) THEN
                            exam_i = floor((random()*(10-1)+1));
                        ELSE
                            exam_i = pointer.exam_grade;
                        END IF;
                        IF (pointer.lab_grade IS NULL AND  pointer.lab_hours > 0) THEN
                            lab_i = floor((random()*(10-1)+1));
                        ELSE
                            lab_i = pointer.lab_grade;
                        END IF;
                        percentage = (SELECT exam_percentage FROM "CourseRun" 
                                      WHERE course_code = pointer.course_code AND serial_number = pointer.serial_number);
                        UPDATE "Register" r
                        SET lab_grade = lab_i ,exam_grade = exam_i,
                            final_grade = (SELECT
                                           CASE WHEN pointer.lab_hours IS NOT NULL 
                                           THEN (floor(((lab_i*(100-percentage)) + exam_i * percentage)/100))
                                           ELSE (exam_i)
                                           END)
                        WHERE (final_grade IS NULL)
                        AND r.amka = pointer.amka  
                        AND r.course_code = pointer.course_code
                        AND r.register_status = 'approved';
                        
                    END LOOP;
END;
$$

LANGUAGE 'plpgsql';
-- Table: public.CourseRun

-- DROP TABLE IF EXISTS public."CourseRun";

CREATE TABLE IF NOT EXISTS public."CourseRun"
(
    course_code character(7) COLLATE pg_catalog."default" NOT NULL,
    serial_number integer NOT NULL,
    exam_min numeric,
    lab_min numeric,
    exam_percentage numeric,
    labuses integer,
    semesterrunsin integer NOT NULL,
    CONSTRAINT "CourseRun_pkey" PRIMARY KEY (course_code, serial_number),
    CONSTRAINT "CourseRun_course_code_fkey" FOREIGN KEY (course_code)
        REFERENCES public."Course" (course_code) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT "CourseRun_labuses_fkey" FOREIGN KEY (labuses)
        REFERENCES public."Lab" (lab_code) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT "CourseRun_semesterrunsin_fkey" FOREIGN KEY (semesterrunsin)
        REFERENCES public."Semester" (semester_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS public."CourseRun"
    OWNER to postgres;
-- Table: public.Course

-- DROP TABLE IF EXISTS public."Course";

CREATE TABLE IF NOT EXISTS public."Course"
(
    course_code character(7) COLLATE pg_catalog."default" NOT NULL,
    course_title character(100) COLLATE pg_catalog."default" NOT NULL,
    units smallint NOT NULL,
    lecture_hours smallint NOT NULL,
    tutorial_hours smallint NOT NULL,
    lab_hours smallint NOT NULL,
    typical_year smallint NOT NULL,
    typical_season semester_season_type NOT NULL,
    obligatory boolean NOT NULL,
    course_description character varying COLLATE pg_catalog."default",
    CONSTRAINT "Course_pkey" PRIMARY KEY (course_code)
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS public."Course"
    OWNER to postgres;
-- Table: public.Register

-- DROP TABLE IF EXISTS public."Register";

CREATE TABLE IF NOT EXISTS public."Register"
(
    amka character varying COLLATE pg_catalog."default" NOT NULL,
    serial_number integer NOT NULL,
    course_code character(7) COLLATE pg_catalog."default" NOT NULL,
    exam_grade numeric,
    final_grade numeric,
    lab_grade numeric,
    register_status register_status_type,
    CONSTRAINT "Register_pkey" PRIMARY KEY (course_code, serial_number, amka),
    CONSTRAINT "Register_course_run_fkey" FOREIGN KEY (serial_number, course_code)
        REFERENCES public."CourseRun" (serial_number, course_code) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE CASCADE,
    CONSTRAINT "Register_student_fkey" FOREIGN KEY (amka)
        REFERENCES public."Student" (amka) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE CASCADE
        NOT VALID
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS public."Register"
    OWNER to postgres;

希望对你有所帮助。

英文:

So I database for a university and I need to update several columns of a table named register going with the name of exam_grade, lab_grade, and final grade. The final grade is calculated based on the results of exam_grade and lab_grade, but whenever the result of lab_grade is NULL then the result of final_grade is not becoming directly the exam_grade, but also stays NULL. Here is the code for the function:


CREATE OR REPLACE FUNCTION public.fn_question_2_2(num integer)
RETURNS void
AS
$$
DECLARE
pointer record;
percentage numeric;
exam_i numeric;
lab_i numeric;
BEGIN
FOR pointer IN
(SELECT rg.amka, rg.lab_grade, rg.exam_grade,
rg.serial_number, rg.register_status, 
cr.course_code, cr.lab_hours
FROM "Register" rg
JOIN (SELECT course_code, lab_hours FROM "Course") cr USING (course_code)
WHERE rg.register_status = 'approved' AND rg.serial_number = num)
LOOP
IF (pointer.exam_grade IS NULL) THEN
exam_i = floor((random()*(10-1)+1));
ELSE
exam_i = pointer.exam_grade;
END IF;
IF (pointer.lab_grade IS NULL AND  pointer.lab_hours > 0) THEN
lab_i = floor((random()*(10-1)+1));
ELSE
lab_i = pointer.lab_grade;
END IF;
percentage = (SELECT exam_percentage FROM "CourseRun" 
WHERE course_code = pointer.course_code AND serial_number = pointer.serial_number);
UPDATE "Register" r
SET lab_grade = lab_i ,exam_grade = exam_i,
final_grade = (SELECT
CASE WHEN pointer.lab_hours IS NOT NULL 
THEN (floor(((lab_i*(100-percentage)) + exam_i * percentage)/100))
ELSE (exam_i)
END)
WHERE (final_grade IS NULL)
AND r.amka = pointer.amka  
AND r.course_code = pointer.course_code
AND r.register_status = 'approved';
END LOOP;
END;
$$
LANGUAGE 'plpgsql';

-- DROP TABLE IF EXISTS public."CourseRun";
CREATE TABLE IF NOT EXISTS public."CourseRun"
(
course_code character(7) COLLATE pg_catalog."default" NOT NULL,
serial_number integer NOT NULL,
exam_min numeric,
lab_min numeric,
exam_percentage numeric,
labuses integer,
semesterrunsin integer NOT NULL,
CONSTRAINT "CourseRun_pkey" PRIMARY KEY (course_code, serial_number),
CONSTRAINT "CourseRun_course_code_fkey" FOREIGN KEY (course_code)
REFERENCES public."Course" (course_code) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
CONSTRAINT "CourseRun_labuses_fkey" FOREIGN KEY (labuses)
REFERENCES public."Lab" (lab_code) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
CONSTRAINT "CourseRun_semesterrunsin_fkey" FOREIGN KEY (semesterrunsin)
REFERENCES public."Semester" (semester_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public."CourseRun"
OWNER to postgres;```
```-- Table: public.Course
-- DROP TABLE IF EXISTS public."Course";
CREATE TABLE IF NOT EXISTS public."Course"
(
course_code character(7) COLLATE pg_catalog."default" NOT NULL,
course_title character(100) COLLATE pg_catalog."default" NOT NULL,
units smallint NOT NULL,
lecture_hours smallint NOT NULL,
tutorial_hours smallint NOT NULL,
lab_hours smallint NOT NULL,
typical_year smallint NOT NULL,
typical_season semester_season_type NOT NULL,
obligatory boolean NOT NULL,
course_description character varying COLLATE pg_catalog."default",
CONSTRAINT "Course_pkey" PRIMARY KEY (course_code)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public."Course"
OWNER to postgres;```
```-- Table: public.Register
-- DROP TABLE IF EXISTS public."Register";
CREATE TABLE IF NOT EXISTS public."Register"
(
amka character varying COLLATE pg_catalog."default" NOT NULL,
serial_number integer NOT NULL,
course_code character(7) COLLATE pg_catalog."default" NOT NULL,
exam_grade numeric,
final_grade numeric,
lab_grade numeric,
register_status register_status_type,
CONSTRAINT "Register_pkey" PRIMARY KEY (course_code, serial_number, amka),
CONSTRAINT "Register_course_run_fkey" FOREIGN KEY (serial_number, course_code)
REFERENCES public."CourseRun" (serial_number, course_code) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT "Register_student_fkey" FOREIGN KEY (amka)
REFERENCES public."Student" (amka) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
NOT VALID
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public."Register"
OWNER to postgres;```
amka|serial_number|course_code|exam_grade|final_grade|lab_grade|semes_status
"01010104188"	12	"ΑΓΓ 201"	6	6	10	"pass"
"01010104188"	12	"ΑΓΓ 202"	2			"approved"
"01010104188"	12	"ΗΡΥ 201"	8	9	10	"pass"
"01010104188"	12	"ΗΡΥ 202"	9	8	7	"pass"
"01010104188"	12	"ΗΡΥ 203"	7	8.40	9	"approved"
"01010104188"	12	"ΗΡΥ 204"	7	5.50	4	"approved"
"01010104188"	12	"ΗΡΥ 211"	9			"approved"
"01010104188"	12	"ΜΑΘ 107"	2	2	6	"fail"
"01010104188"	12	"ΠΛΗ 201"	7	0	2	"fail"
"01010104188"	12	"ΠΛΗ 202"	2	2.70	3	"approved"
"01010104188"	12	"ΠΛΗ 211"	8	7	5	"pass"
"01010104188"	12	"ΤΗΛ 201"	7	7	7	"pass"
"01010104188"	12	"ΤΗΛ 202"	4	3.20	2	"approved"
"01010104188"	12	"ΤΗΛ 211"	5	7.00	9	"approved"

Any help will be appreciated, and if anything needs to be added so that you get a better perspective please say so.

I tried many different ways of writing the query and the results are every time the same. I cannot get the final_grade = exam_ grade when the lab_grade is NULL. I don't get any error message so there is a problem with the logic.

答案1

得分: 1

你可以使用 COALESCE 或在你的 CASE 语句中进行检查:

英文:

You can either use COALESCE or check in your CASE:


CREATE OR REPLACE FUNCTION public.fn_question_2_2(num integer)
RETURNS void
AS
$$
DECLARE
       pointer record;
       percentage numeric;
       exam_i numeric;
       lab_i numeric;
BEGIN
     FOR pointer IN
                   (SELECT rg.amka, rg.lab_grade, rg.exam_grade,
                           rg.serial_number, rg.register_status, 
                           cr.course_code, cr.lab_hours
                    FROM "Register" rg
                    JOIN (SELECT course_code, lab_hours FROM "Course") cr USING (course_code)
                    WHERE rg.register_status = 'approved' AND rg.serial_number = num)
                    LOOP
                        IF (pointer.exam_grade IS NULL) THEN
                            exam_i = floor((random()*(10-1)+1));
                        ELSE
                            exam_i = pointer.exam_grade;
                        END IF;
                        IF (pointer.lab_grade IS NULL AND  pointer.lab_hours > 0) THEN
                            lab_i = floor((random()*(10-1)+1));
                        ELSE
                            lab_i = pointer.lab_grade;
                        END IF;
                        percentage = (SELECT exam_percentage FROM "CourseRun" 
                                      WHERE course_code = pointer.course_code AND serial_number = pointer.serial_number);
                        UPDATE "Register" r
                        SET lab_grade = lab_i ,exam_grade = exam_i,
                            final_grade = (SELECT
                                               CASE WHEN pointer.lab_hours IS NOT NULL 
                                               THEN (floor(((COALESCE(lab_i, 0)*(100-percentage)) + exam_i * percentage)/100))
                                               ELSE (exam_i)
                                               END)
                        WHERE (final_grade IS NULL)
                        AND r.amka = pointer.amka  
                        AND r.course_code = pointer.course_code
                        AND r.register_status = 'approved';
                        
                    END LOOP;
END;
$$

LANGUAGE 'plpgsql';

or


CREATE OR REPLACE FUNCTION public.fn_question_2_2(num integer)
RETURNS void
AS
$$
DECLARE
       pointer record;
       percentage numeric;
       exam_i numeric;
       lab_i numeric;
BEGIN
     FOR pointer IN
                   (SELECT rg.amka, rg.lab_grade, rg.exam_grade,
                           rg.serial_number, rg.register_status, 
                           cr.course_code, cr.lab_hours
                    FROM "Register" rg
                    JOIN (SELECT course_code, lab_hours FROM "Course") cr USING (course_code)
                    WHERE rg.register_status = 'approved' AND rg.serial_number = num)
                    LOOP
                        IF (pointer.exam_grade IS NULL) THEN
                            exam_i = floor((random()*(10-1)+1));
                        ELSE
                            exam_i = pointer.exam_grade;
                        END IF;
                        IF (pointer.lab_grade IS NULL AND  pointer.lab_hours > 0) THEN
                            lab_i = floor((random()*(10-1)+1));
                        ELSE
                            lab_i = pointer.lab_grade;
                        END IF;
                        percentage = (SELECT exam_percentage FROM "CourseRun" 
                                      WHERE course_code = pointer.course_code AND serial_number = pointer.serial_number);
                        UPDATE "Register" r
                        SET lab_grade = lab_i ,exam_grade = exam_i,
                            final_grade = (SELECT
                                               CASE WHEN pointer.lab_hours IS NOT NULL AND lab_i IS NOT NULL
                                               THEN (floor(((lab_i*(100-percentage)) + exam_i * percentage)/100))
                                               ELSE (exam_i)
                                               END)
                        WHERE (final_grade IS NULL)
                        AND r.amka = pointer.amka  
                        AND r.course_code = pointer.course_code
                        AND r.register_status = 'approved';
                        
                    END LOOP;
END;
$$

LANGUAGE 'plpgsql';

答案2

得分: 0

你的子查询是我们需要检查问题的地方,因为你抱怨的是错误的数值导致了更新,而不是数值变化的缺失。因此,让我们看看这个子查询:

SELECT
CASE WHEN pointer.lab_hours IS NOT NULL 
     THEN (floor(((lab_i*(100-percentage)) + exam_i * percentage)/100))
     ELSE (exam_i)
END

NULL 是一个吸收元素,所以,无论你对它执行什么操作,结果都将是 NULL。原因很简单:NULL 是缺少值,或者换句话说,它是未知的。那么,例如

未知 + 2

的结果是什么呢?自然是未知。

因此,如果不太了解你正在测试的数据,以下是可能具有 NULL 值的字段:

  • lab_i
  • percentage
  • exam_i

因此,你可能需要弄清楚默认值应该是什么,并将这样的默认值用作对 COALESCE 的调用的参数,形式为 COALESCE(<你的字段或表达式>, <首选默认值>)

英文:

Your subquery is the place where we need to check what the problem is, because, since you complained on the wrong value resulting in the update and not a lack of value change. Hence, let's see this subquery:

SELECT
CASE WHEN pointer.lab_hours IS NOT NULL 
THEN (floor(((lab_i*(100-percentage)) + exam_i * percentage)/100))
ELSE (exam_i)
END

NULL is an absorbing element, so, whatever operation you perform with it, the result will be NULL. The reason is simple: NULL is the lack of value, or, in other words, it is the unknown. So, what's the result of

unkown + 2

for example? Naturally, it's unknown.

So, without knowing too much about the data you are testing, these are the fields that could have a NULL value:

  • lab_i
  • percentage
  • exam_i

So, you will likely need to figure out what the default value should be and use such a default value as a parameter to a call for COALESCE, of the form of COALESCE(&lt;your field or expression&gt;, &lt;the preferred default&gt;)

huangapple
  • 本文由 发表于 2023年5月6日 23:23:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定