Как посчитать количество строк без повторения заданного значения в ПРОЦЕДУРЕ - PullRequest
2 голосов
/ 16 апреля 2020

Oracle Используется SQL + (PL / SQL) *

Как подсчитать количество лигни в аналогичном случае, используя ПРОЦЕДУРУ:

Пример таблицы

CREATE TABLE Teacher
(name         CHAR(7)       NOT NULL,
 lastName     INTEGER       NOT NULL,
 teacherCode  CHAR(5)       NOT NULL,
CONSTRAINT PrimaryKey PRIMARY KEY (name)
);

CREATE TABLE Class
(acronym           CHAR(7)      NOT NULL,
 groupNum          INTEGER      NOT NULL,
 sessionCode       INTEGER      NOT NULL,
 teacherCode        CHAR(5)     NOT NULL,
CONSTRAINT P_Key PRIMARY KEY (acronym)
CONSTRAINT F_Key FOREIGN KEY (teacherCode)
);

Я хочу посчитать количество классов, которые определенный учитель дал для каждой сессии .

Пример данных в таблице

Teacher
John Jonas JJ000 
zzzz zzzzz zzzzz
zzzz zzzzz zzzzz
...

Class
XXX1000 10 1000 JJ000
zzzzzzz zz zzzz zzzzz
XXX3333 16 2000 JJ000
zzzzzzz zz zzzz zzzzz
XXX2222 12 1000 JJ000
zzzzzzz zz zzzz zzzzz
XXX1000 13 2000 JJ000
zzzzzzz zz zzzz zzzzz
XXX9999 16 2000 JJ000

Я хотел бы получить следующую распечатку:

Code of the teacher: JJ000
Name:                John
Last name:           Jonas
Number of classes given in the session 1000: 2
Number of classes given in the session 2000: 3

Вот как выглядит моя ПРОЦЕДУРА до сих пор:

CREATE OR REPLACE PROCEDURE numberOfGiverClasses
(codeOfTeacher Teacher.teacherCode%TYPE) IS
    v_teacherCode       Teacher.teacherCode%TYPE;
    v_name              Teacher.name%TYPE;
    v_lastName          Teacher.lastName%TYPE;
    v_nbGivenClasses    INTEGER;
    v_sessionCode       Class.sessionCode%TYPE;

BEGIN
    SELECT teacherCode, name, lastName
    INTO v_teacherCode, v_name, v_lastName
    FROM Teacher
    WHERE teacherCode = codeOfTeacher ;

    DBMS_OUTPUT.PUT('Code of the teacher: ');
    DBMS_OUTPUT.PUT_LINE(v_teacherCode);
    DBMS_OUTPUT.PUT('Name: ');
    DBMS_OUTPUT.PUT_LINE(v_name);
    DBMS_OUTPUT.PUT('Last name: ');
    DBMS_OUTPUT.PUT_LINE(v_lastName);

    ????

    DBMS_OUTPUT.PUT('Number of classes given in the session ');
    DBMS_OUTPUT.PUT(v_sessionCode);
    DBMS_OUTPUT.PUT(': ');
    DBMS_OUTPUT.PUT(v_nbGivenClasses);

END numberOfGiverClasses;

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Добро пожаловать на ТАК!

Во-первых, у вашей схемы / синтаксиса есть несколько проблем:

1. Teacher.lastName объявлен как INTEGER - должен быть вместо этого varchar?
2. Class.acronym определен как первичный ключ, но имеет дубликаты, основанные на ваших данных - должен ли groupNum быть первичным ключом вместо этого?
3. F_Key отсутствует ссылка на столбец
4. teacherCode не определен как первичный ключ в таблице Teacher

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

create table teacher
(
   name          varchar2 (10) not null,
   lastname      varchar2 (10) not null,
   teachercode   varchar2 (10) not null,
   constraint primarykey primary key (teachercode)
);


create table class
(
   acronym       varchar2 (10) not null,
   groupnum      integer not null,
   sessioncode   integer not null,
   teachercode   varchar2 (10) not null,
   constraint p_key primary key (groupnum),
   constraint f_key foreign key (teachercode) references teacher (teachercode)
);


insert into teacher  select 'John', 'Jonas', 'JJ000' from dual;
commit;


insert into class
   select 'XXX1000' acronym, 10 groupnum, 1000 sessioncode, 'JJ000' teachercode from dual union all
   select 'XXX3333', 16, 2000, 'JJ000' from dual union all
   select 'XXX2222', 12, 1000, 'JJ000' from dual union all
   select 'XXX1000', 13, 2000, 'JJ000' from dual union all
   select 'XXX9999', 17, 2000, 'JJ000' from dual;
commit;


select * from teacher;

| NAME    |LASTNAME    |TEACHERCODE |
| John    |Jonas       |JJ000       |


select * from class;

|ACRONYM    |GROUPNUM   |SESSIONCODE    |TEACHERCODE    |
|XXX1000    |10         |1000           |JJ000          |
|XXX3333    |16         |2000           |JJ000          |
|XXX2222    |12         |1000           |JJ000          |
|XXX1000    |13         |2000           |JJ000          |
|XXX9999    |17         |2000           |JJ000          |


Вы можете распечатать количество классов за сеанс, используя курсор для l oop внутри профи c. Вы можете изменить курсор в зависимости от ваших требований.

Образец выглядит следующим образом ..

CREATE OR REPLACE PROCEDURE numberOfGiverClasses
(codeOfTeacher Teacher.teacherCode%TYPE) IS
    v_teacherCode       Teacher.teacherCode%TYPE;
    v_name              Teacher.name%TYPE;
    v_lastName          Teacher.lastName%TYPE;

BEGIN
    SELECT teacherCode, name, lastName
    INTO v_teacherCode, v_name, v_lastName
    FROM Teacher
    WHERE teacherCode = codeOfTeacher ;

    DBMS_OUTPUT.PUT_LINE(rpad('Code of the teacher: ',25) || v_teacherCode);
    DBMS_OUTPUT.PUT_LINE(rpad('Name: ',25) || v_name);
    DBMS_OUTPUT.PUT_LINE(rpad('Last name: ',25) || v_lastName);

    for o in (
    select sessioncode, count(groupnum) cnt from class
    where teachercode = v_teacherCode
    group by sessioncode
    ) loop
        DBMS_OUTPUT.PUT_LINE('Number of classes given in the session ' || o.sessionCode ||': ' ||o.cnt );
    end loop;

exception when others then
    dbms_output.put_line(sqlerrm);         
END numberOfGiverClasses;


Образец исполнения

set serveroutput on size unlimited
begin
numberOfGiverClasses('JJ000');
end;


Выход:

Code of the teacher:     JJ000
Name:                    John
Last name:               Jonas
Number of classes given in the session 1000: 2
Number of classes given in the session 2000: 3


Если это не сработает, пожалуйста, уточните свой вопрос с дополнительной информацией
Если это соответствует вашим требованиям, не стесняйтесь принять и голос

1 голос
/ 16 апреля 2020

Вы можете достичь этого, используя GROUP BY в одном запросе следующим образом:

SQL> -- Your data
SQL> with teacher as
  2  (select 'John' name, 'Jonas' lastname, 'JJ000' teachercode from dual),
  3  class as
  4  (select 'XXX1000' acronym, 10 groupnum, 1000 sessioncode, 'JJ000' teachercode from dual union all
  5     select 'XXX3333', 16, 2000, 'JJ000' from dual union all
  6     select 'XXX2222', 12, 1000, 'JJ000' from dual union all
  7     select 'XXX1000', 13, 2000, 'JJ000' from dual union all
  8     select 'XXX9999', 17, 2000, 'JJ000' from dual)
  9  --
 10  -- actual query starts from here
 11  SELECT
 12      'Code of the teacher: ' || TEACHERCODE || CHR(10)
 13      || 'Name:               ' || NAME || CHR(10)
 14      || 'Last name:           ' || LASTNAME || CHR(10)
 15      || LISTAGG('Number of classes given in the session ' || SESSIONCODE || ' : ' || CNT, CHR(10))
 16              WITHIN GROUP(ORDER BY CNT)
 17  FROM ( SELECT T.TEACHERCODE, T.NAME, T.LASTNAME, C.SESSIONCODE, COUNT(1) AS CNT
 18          FROM TEACHER T JOIN CLASS C ON T.TEACHERCODE = C.TEACHERCODE
 19          GROUP BY T.TEACHERCODE, T.NAME, T.LASTNAME, C.SESSIONCODE
 20       )
 21  GROUP BY TEACHERCODE, NAME, LASTNAME;

'CODEOFTHETEACHER:'||TEACHERCODE||CHR(10)||'NAME:'||NAME||CHR(10)||'LASTNAME:'||
--------------------------------------------------------------------------------
Code of the teacher: JJ000
Name:               John
Last name:           Jonas
Number of classes given in the session 1000 : 2
Number of classes given in the session 2000 : 3


SQL>
...