SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 20.02.2013 01:40:11

webber
Участник
Зарегистрирован: 20.02.2013
Сообщений: 9

Дописать запрос

Есть две таблицы:
http://s019.radikal.ru/i601/1302/20/60bf9912c1d1.jpg
и
http://s017.radikal.ru/i442/1302/de/3a244e8c2fe8.jpg

Нужно: Написать запрос, который выдает список фамилий студентов, с комментарием 'успевает' у студентов, имеющих все положительные оценки, комментарием 'не успевает' для имеющих хотя бы одну неудовлетворительную оценку и комментарием 'не сдавал' — для всех остальных. В выводимом результате фамилии студентов упорядочить по алфавиту.

У меня получилось примерно следующее:

SELECT st.`SURNAME` , CASE WHEN em.`MARK`>3 THEN "успевает" WHEN em.`MARK`<4 THEN "не успевает" ELSE "не сдавал" END AS `Koment`
    FROM `student` AS  st, `exam_marks` AS em      
    WHERE st.STUDENT_ID IN(SELECT em.`STUDENT_ID` FROM `exam_marks`
 GROUP BY em.`STUDENT_ID`);

Но результат далек от совершенства( Помогите дописать/переделать запрос

Неактивен

 

#2 20.02.2013 09:16:47

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Дописать запрос

Возникло несколько вопросов:
1) Что значит "далёк от совершенства"? Чем результат не устроил?
2) Нужно ли выводить в итоговом списке тех студентов, у которых нет ни одной оценки ни по одному предмету?
3) В таблице с оценками, Вами приведенной, в одной записи оценка отсутствовала ( где exam_id = 639). Это что означает - неуд? неявка? То есть непонятно, считать ли это неудовлетворительной оценкой,

И приведите пожалуйста
структуру Ваших таблиц и данные в формате show create table `student` и show create table `exam_marks`,
данные в виде insert into.. (можно просто тестовый набор) и
результ, который Вы хотите получить.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 20.02.2013 11:05:53

webber
Участник
Зарегистрирован: 20.02.2013
Сообщений: 9

Re: Дописать запрос

1) В результате мне выдает список только тех студентов, что есть в `exam_marks`,
а комментарии, как я понял, присваиваются исходя только из большей оценки( например, у студента оценки 2 и 5, комментарий будет "успевает" хотя должен быть "не успевает")
2) Да, это и есть те кто "не сдавал"
3) Это означает изначально идиотские таблицы данные преподавателем, можно это просто проигнорировать

CREATE TABLE EXAM_MARKS (
    EXAM_ID        INTEGER NOT NULL,
    STUDENT_ID  INTEGER,
    SUBJ_ID        INTEGER,
    MARK           SMALLINT,
    EXAM_DATE      DATE
);

CREATE TABLE STUDENT (
    STUDENT_ID  INTEGER NOT NULL,
    SURNAME     VARCHAR(20),
    NAME        VARCHAR(15),
    STIPEND     INTEGER,
    KURS        SMALLINT,
    CITY        VARCHAR(25),
    BIRTHDAY    DATE,
    UNIV_ID     INTEGER
);


То, что я хочу должно выглядеть так:

`SURNAME`           | `Koment`
Тут все фамилии   | каждой фамилии
из таблицы           | соответствует 1 из комментариев
`student`             | "успевает", "не успевает" или "не сдавал"

Неактивен

 

#4 20.02.2013 11:43:06

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Дописать запрос

В-общем, вид монстрооборазный, конечно, но работает вроде  - проверяйте.



CREATE TABLE `t_6493_STUDENT` (
  `STUDENT_ID` int NOT NULL,
  `SURNAME` varchar(20) DEFAULT NULL,
  `NAME` varchar(15) DEFAULT NULL,
  `STIPEND` int DEFAULT NULL,
  `KURS` smallint DEFAULT NULL,
  `CITY` varchar(25) DEFAULT NULL,
  `BIRTHDAY` date DEFAULT NULL,
  `UNIV_ID` int DEFAULT NULL
) ENGINE=MyISAM;

CREATE TABLE `t_6493_EXAM_MARKS` (
  `EXAM_ID` int NOT NULL,
  `STUDENT_ID` int(11) DEFAULT NULL,
  `SUBJ_ID` int DEFAULT NULL,
  `MARK` smallint DEFAULT NULL,
  `EXAM_DATE` date DEFAULT NULL
) ENGINE=MyISAM;
insert into t_6493_STUDENT(STUDENT_ID, SURNAME) VALUES(1,'Ivanov'),(2,'Petrov'),(3,'Sidorov');
insert into t_6493_EXAM_MARKS(EXAM_ID, STUDENT_ID, SUBJ_ID, MARK) VALUES(1,1,1,3),(2,1,2,2),(1,2,1,5),(2,2,2,5);

Результат

SELECT
    SURNAME,
  CASE
  WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID) = 0 THEN
    'НЕ СДАВАЛ'
  ELSE
    CASE
    WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID AND MARK <= 2) > 0 THEN
      'НЕ УСПЕВАЕТ'
    ELSE
      'УСПЕВАЕТ'
    END
  END
FROM
    t_6493_STUDENT s;
 


Код:

mysql> SELECT
    -> SURNAME,
    ->   CASE
    ->   WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID) = 0 THEN
    ->     'НЕ СДАВАЛ'
    ->   ELSE
    ->     CASE
    ->     WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID AND MARK <= 2) > 0 THEN
    ->       'НЕ УСПЕВАЕТ'
    ->     ELSE
    ->       'УСПЕВАЕТ'
    ->     END
    ->   END as commentary
    -> FROM
    -> t_6493_STUDENT s;
+---------+-----------------------+
| SURNAME | commentary            |
+---------+-----------------------+
| Ivanov  | НЕ УСПЕВАЕТ |
| Petrov  | УСПЕВАЕТ      |
| Sidorov | НЕ СДАВАЛ     |
+---------+-----------------------+
3 rows in set (0.00 sec)

Иванов сдал математику на три, физику на два - не успевает
Петров отличник - сдал и математику и физику на 5 - успевает.
Сидоров ни разу не пришёл, ничего не сдавал - не сдавал.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#5 20.02.2013 14:33:47

webber
Участник
Зарегистрирован: 20.02.2013
Сообщений: 9

Re: Дописать запрос

Спасибо, все работает, только второй CASE по сути не нужен, то есть:

CASE
       WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID) = 0 THEN
         'НЕ СДАВАЛ'
        WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID AND MARK <= 2) > 0 THEN
           'НЕ УСПЕВАЕТ'
        ELSE
           'УСПЕВАЕТ'      
       END as commentary


И еще, логичнее count(STUDENT_ID) вместо count(*) или здесь это не имеет значения?

Неактивен

 

#6 20.02.2013 16:30:22

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Дописать запрос

Насчет второго case'a -  это уже скорее вопрос "дизайна" запроса, мне мой вариант кажется более читабельным smile.

Что касается count(STUDENT_ID) - поскольку STUDENT_ID не должно быть равно NULL ( хоть в Вашей структуре и не указано, что NOT NULL - но строка с нулевым student_id не имеет смысла, ведь оценка должна быть кому-то поставлена! ), то особой разницы нет.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#7 28.02.2013 20:34:15

webber
Участник
Зарегистрирован: 20.02.2013
Сообщений: 9

Re: Дописать запрос

Снова, здравствуйте
Можете еще помочь переписать

SELECT
    SURNAME,
  CASE
  WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID) = 0 THEN
    'НЕ СДАВАЛ'
  ELSE
    CASE
    WHEN (SELECT count(*) from t_6493_EXAM_MARKS WHERE STUDENT_ID = s.STUDENT_ID AND MARK <= 2) > 0 THEN
      'НЕ УСПЕВАЕТ'
    ELSE
      'УСПЕВАЕТ'
    END
  END
FROM
    t_6493_STUDENT s;
 


без использования вложенных SELECTов, а то, что-то никак не соображу..(

Неактивен

 

#8 03.03.2013 23:56:17

webber
Участник
Зарегистрирован: 20.02.2013
Сообщений: 9

Re: Дописать запрос

ап..(

Неактивен

 

#9 04.03.2013 00:55:08

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Дописать запрос

Не уверен, что такой запрос хорошо переписывается без вложенных селектов. Да и зачем?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#10 04.03.2013 00:58:27

webber
Участник
Зарегистрирован: 20.02.2013
Сообщений: 9

Re: Дописать запрос

deadka, прихоть преподавателя)

Неактивен

 

#11 04.03.2013 01:38:14

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Дописать запрос

Экий прихотливый smile

SELECT
  s.STUDENT_ID,
  s.SURNAME,
  CASE
    WHEN ( max( coalesce(MARK,0) )=0 ) THEN
      'НЕ СДАВАЛ'
    ELSE
      CASE
        WHEN max(CASE WHEN MARK<3 THEN 1 ELSE 0 END) THEN
          'НЕ УСПЕВАЕТ'
        ELSE
          'УСПЕВАЕТ'
        END
    END
FROM t_6493_STUDENT s LEFT JOIN t_6493_EXAM_MARKS using(STUDENT_ID) group by s.STUDENT_ID;


Код:

mysql> SELECT
    ->   s.STUDENT_ID,
    ->   s.SURNAME,
    ->   CASE
    ->     WHEN ( max( coalesce(MARK,0) )=0 ) THEN
    ->       'НЕ СДАВАЛ'
    ->     ELSE
    ->       CASE
    ->         WHEN max(CASE WHEN MARK<3 THEN 1 ELSE 0 END) THEN
    ->           'НЕ УСПЕВАЕТ'
    ->         ELSE
    ->           'УСПЕВАЕТ'
    ->       END
    ->   END as `result`
    -> from t_6493_STUDENT s LEFT JOIN t_6493_EXAM_MARKS using(STUDENT_ID) group by s.STUDENT_ID;
+------------+---------+-----------------------+
| STUDENT_ID | SURNAME | result                |
+------------+---------+-----------------------+
|          1 | Ivanov  | НЕ УСПЕВАЕТ |
|          2 | Petrov  | УСПЕВАЕТ      |
|          3 | Sidorov | НЕ СДАВАЛ     |
+------------+---------+-----------------------+
3 rows in set (0.00 sec)

Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#12 04.03.2013 02:05:05

webber
Участник
Зарегистрирован: 20.02.2013
Сообщений: 9

Re: Дописать запрос

Спасибо, выручаете меня

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson