2016-05-10 4 views
2

У меня есть два MySQL величайшего-н-в-группа, самые большие по дате проблема:MySQL макс в группу по дате

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

Сценарий схемы:

CREATE TABLE student (
     id int(11) NOT NULL AUTO_INCREMENT, 
     `name` varchar(255) NOT NULL, 
     PRIMARY KEY (id) 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

    INSERT INTO student VALUES(1, 'jim'); 
    INSERT INTO student VALUES(2, 'mark '); 
    INSERT INTO student VALUES(3, 'john'); 

    CREATE TABLE grades (
     id int(11) NOT NULL AUTO_INCREMENT, 
     student_id int(11) NOT NULL, 
     grade int(11) NOT NULL, 
     `date` date DEFAULT NULL, 
     PRIMARY KEY (id) 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 


    INSERT INTO grades VALUES(1, 1, 6, NULL); 
    INSERT INTO grades VALUES(2, 1, 8, NULL); 
    INSERT INTO grades VALUES(3, 1, 10, NULL); 
    INSERT INTO grades VALUES(4, 2, 9, '2016-05-10'); 
    INSERT INTO grades VALUES(5, 2, 8, NULL); 
    INSERT INTO grades VALUES(6, 3, 6, '2016-05-26'); 
    INSERT INTO grades VALUES(7, 3, 7, '2016-05-27'); 

A) Я хочу, чтобы выяснить, является ли это правильным решением для получения самой последней записи на поле даты (date) из вспомогательной таблицы (grades), сгруппированных по каждая строка в основной таблице (student).

Мой запрос:

SELECT s.id, s.name, g.grade, g.date 
    FROM student AS s 
    LEFT JOIN (
     SELECT student_id, grade, DATE 
     FROM grades AS gr 
     WHERE DATE = (
      SELECT MAX(DATE) 
      FROM grades 
      WHERE student_id = gr.student_id 
     ) 
     GROUP BY student_id 
    ) AS g ON s.id = g.student_id 

Sql Fiddle: http://sqlfiddle.com/#!9/a84171/2

Этот запрос отображает желательные (почти) результаты. Но у меня есть сомнения, что это лучший подход, потому что он выглядит уродливым, поэтому мне очень любопытно об альтернативах.

В) Второй проблемой является причиной для вышеупомянутого (almost),

В первом ряду, name=Jim он не находит класса, хотя у нас есть классы для Jim. Так что на всякий случай, если запрос выше будет действителен только для полей даты NOT NULL. Вопрос был бы:

Как получить последний класс для всех учащихся, имеющих оценки, в том числе Джима, даже если его оценки не указаны (NULL). В этом случае самая последняя группировка будет определяться последней введенной строкой (MAX (id)) или просто случайной.

Не работает с заменой date = (SELECT... на date IN (SELECT ....

Любая помощь будет высоко ценится,

Спасибо!

[ОБНОВЛЕНИЕ # 1]:

Для B) я нашел добавив в суб-запроса, OR date IS NULL, производит желаемый результат:

SELECT s.id, s.name, g.grade, g.date 
    FROM student AS s 
    LEFT JOIN (
     SELECT id, student_id, grade, DATE 
     FROM grades AS gr 
     WHERE DATE = (
      SELECT MAX(DATE) 
      FROM grades 
      WHERE student_id = gr.student_id 
     ) OR date IS NULL 
     GROUP BY student_id 
    ) AS g ON s.id = g.student_id 

[UPDATE # 2]

Кажется, что предыдущее обновление работало, если у первого класса есть дата для ученика. Это не так, если первый класс равен нулю. Я бы связал скрипку, но, похоже, sqlfiddle не работает.

Так вот что я придумал до сих пор, что, кажется, решить эту проблему B):

SELECT s.id, s.name, g.grade, g.date 
    FROM student AS s 
    LEFT JOIN (
     SELECT id, student_id, grade, DATE 
     FROM grades AS gr 
     WHERE (
      `date` = (
       SELECT MAX(DATE) 
       FROM grades 
       WHERE student_id = gr.student_id 
      ) 
     ) OR (
      (
       SELECT MAX(DATE) 
       FROM grades 
       WHERE student_id = gr.student_id 
      ) IS NULL AND 
      date IS NULL 
     ) 

    ) AS g ON s.id = g.student_id 
    GROUP BY student_id 

Я все еще хотел бы знать, если вы, ребята, знаете, лучше альтернативы этой некрасивой вещи.

Спасибо!

[UPDATE # 3]

@Strawberry Желаемые результаты будут:

id name grade date 
    1 jim  10 NULL 
    2 mark 9 2016-05-10 
    3 john 7 2016-05-27 
  • каждый студент одного соответствующего класса
  • если существует дата для класса, а затем получить самый последний.
+1

Можем ли мы увидеть желаемый результат (ы)? Измените вопрос соответствующим образом. – Strawberry

+0

И как может дата окончания быть NULL? – Strawberry

+0

@Strawberry Я добавил желаемые результаты. В этом примере записи классов могут содержать NULL-дату - должны признать, что это не самый интуитивный, потому что в моей реальной проблеме строки из вторичной таблицы также могут иметь дату NULL. Поэтому давайте просто притворимся, что это отличная от созданной отметки времени записи. –

ответ

1

Сложность этой проблемы связана с логической невозможностью оценки без соответствующей даты, поэтому очевидно, что решение должно исправить это.

Но вот обходной путь ...

т.д .:

SELECT a.* 
    FROM grades a 
    JOIN 
    (SELECT student_id 
      , MAX(COALESCE(UNIX_TIMESTAMP(date),id)) date 
     FROM grades 
     GROUP 
      BY student_id 
    ) b 
    ON b.student_id = a.student_id 
    AND b.date = COALESCE(UNIX_TIMESTAMP(a.date),id); 
0

http://sqlfiddle.com/#!9/ecec43/4

SELECT s.id, s.name, g.grade, g.date 
FROM student AS s 
LEFT JOIN (
    SELECT gr.student_id, gr.grade, gr.DATE 
    FROM grades AS gr 
    LEFT JOIN grades grm 
    ON grm.student_id = gr.student_id 
    AND grm.date>gr.date 
    WHERE grm.student_id IS NULL 
    AND gr.date IS NOT NULL 
    GROUP BY gr.student_id 
) AS g 
ON s.id = g.student_id; 
+0

, это не возвращает оценку для записи даты NULL: 'name = Jim' –

+1

Он возвращает то же самое результат, когда вы получили первоначальный запрос. Я оставил его там, чтобы сравнить результаты – Alex

Смежные вопросы