код работает в точку - PullRequest
       15

код работает в точку

0 голосов
/ 07 декабря 2011

Следующий код выглядит хорошо для меня, но работает до определенного момента.Функция должна отображать уровни успеваемости учащихся на основе результатов экзамена, но она не выполняет последние два других утверждения, и поэтому, если ученик набрал менее 50 баллов, функция по-прежнему отображает «Pass».Кто-нибудь может указать мне на проблему?

Ответы [ 4 ]

1 голос
/ 07 декабря 2011

Это ошибка PostgreSQL, которая меня тоже сбила с толку. Вам необходимо заменить ELSE IF s на ELSIF.

Вы видите эту ошибку, потому что каждый последующий ELSE IF интерпретируется как начало вложенного блока IF, который ожидает свой собственный END IF;.

См. документацию по условным выражениям для получения дополнительной информации о правильном синтаксисе.

0 голосов
/ 08 декабря 2011

Откажитесь от функции в целом и используйте запрос:

SELECT 
  s.*, 
  CASE e.grade 
    WHEN >= 0 AND < 50 THEN 'failed'
    WHEN >= 50 AND < 70 THEN 'passed'
    WHEN >= 70 AND <= 100 THEN 'excellent'
    ELSE 'not taken'
  END
FROM 
 student s,
 entry e
WHERE
 s.sno = e.sno; 
0 голосов
/ 08 декабря 2011

Как правило, я не думаю, что это хорошая идея, чтобы скрыть данные в коде.Данные принадлежат таблицам:

SET search_path='tmp';

-- create some data
DROP TABLE tmp.student CASCADE;
CREATE TABLE tmp.student
    ( sno INTEGER NOT NULL
    , grade INTEGER
    , sname varchar
    );
INSERT INTO tmp.student(sno) SELECT generate_series(1,10);
UPDATE tmp.student SET grade = sno*sno;

DROP TABLE tmp.entry CASCADE;
CREATE TABLE tmp.entry
    ( sno INTEGER NOT NULL
    , sdate TIMESTAMP
    );
INSERT INTO tmp.entry(sno) SELECT generate_series(1,10);

-- table with interval lookup
DROP TABLE tmp.lookup CASCADE;
CREATE TABLE tmp.lookup
    ( llimit NUMERIC NOT NULL
    , hlimit NUMERIC
    , result varchar
    );

INSERT INTO lookup (llimit,hlimit,result)  VALUES(70, NULL, 'Excellent'), (50, 70, 'Passed'), (30, 50, 'Failed')
    ;

CREATE OR REPLACE FUNCTION stud_result(integer,numeric) RETURNS text
AS $BODY$
DECLARE
    stunum ALIAS FOR $1;
    grade ALIAS FOR $2;
    result TEXT;
BEGIN

SELECT COALESCE(lut.result, 'NOT TAKEN')  INTO result
    FROM student st, entry en
    LEFT JOIN lookup lut ON (grade >= lut.llimit
                    AND (grade < lut.hlimit OR lut.hlimit IS NULL) )
    WHERE st.sno = en.sno
     AND st.sno = stunum
    ;
  RETURN result;
END; $BODY$ LANGUAGE PLPGSQL;

-- query joining students with their function values
SELECT st.*
    , stud_result (st.sno, st.grade)
    FROM student st
    ;

Но подождите: вы можете обойтись без уродливой функции:

-- Plain query
SELECT
    st.sno, st.sname, st.grade
    , COALESCE(lut.result, 'NOT TAKEN') AS result
    FROM student st
    LEFT JOIN lookup lut ON ( 1=1
        AND   lut.llimit <= st.grade
        AND ( lut.hlimit > st.grade OR lut.hlimit IS NULL)
        )
    JOIN entry en ON st.sno = en.sno
    ;

Результаты:

 sno | grade | sname | stud_result 
-----+-------+-------+-------------
   1 |     1 |       | NOT TAKEN
   2 |     4 |       | NOT TAKEN
   3 |     9 |       | NOT TAKEN
   4 |    16 |       | NOT TAKEN
   5 |    25 |       | NOT TAKEN
   6 |    36 |       | Failed
   7 |    49 |       | Failed
   8 |    64 |       | Passed
   9 |    81 |       | Excellent
  10 |   100 |       | Excellent
(10 rows)

 sno | sname | grade |  result   
-----+-------+-------+-----------
   1 |       |     1 | NOT TAKEN
   2 |       |     4 | NOT TAKEN
   3 |       |     9 | NOT TAKEN
   4 |       |    16 | NOT TAKEN
   5 |       |    25 | NOT TAKEN
   6 |       |    36 | Failed
   7 |       |    49 | Failed
   8 |       |    64 | Passed
   9 |       |    81 | Excellent
  10 |       |   100 | Excellent
(10 rows)
0 голосов
/ 07 декабря 2011

Ваша логика в условных выражениях немного странная. У вас есть эти:

  • grade >= 70.0
  • grade >= 50.0 OR grade <= 70.0
  • grade > 0 OR grade < 50.0

Обратите внимание, что ноль удовлетворяет второму условию, как и многие другие значения, которые вам не нужны в этой ветви условного выражения. Я думаю, что вы хотите это:

  • grade >= 70.0
  • grade >= 50.0 AND grade <= 70.0
  • grade > 0 AND grade < 50.0

Вы также, кажется, используете свои SELECT, чтобы проверить, находится ли человек в курсе, но если дано grade, а его нет в курсе, вы получите NULL result. Либо проверка «в курсе» должна быть за пределами вашей функции, либо вы должны преобразовать NULL result в 'NOT TAKEN' перед возвратом.

Это похоже на домашнее задание, поэтому я не буду более откровенным, чем это.

...