Запрос на поиск дней с момента непрерывного наблюдения последнего значения столбца - PostgreSQL - PullRequest
0 голосов
/ 04 декабря 2018

Учитывая следующую таблицу, задача состоит в том, чтобы написать SQL-запрос (в PostgreSQL / MySQL - предпочтительно PostgreSQL), который возвращает дни с момента непрерывного наблюдения последнего значения столбца:

Таблица : TestResult

enter image description here

Итак, для ученика с «StudentID = 1001» и «TestID = 2001», так как класс «A» был последнимнаблюдается 2018-12-04 00:00:00, тогда запрос должен возвращать разницу «Дата» для записи с ID = 5014 и ID = 5012;DATE_PART («день», 2018-12-04 00:00:00 - 2018-11-23 00:00:00)

Может кто-нибудь подсказать мне, как написать запрос?Эта таблица будет содержать миллионы записей, поэтому производительность очень важна.При необходимости также может быть предложена лучшая структура схемы таблицы.

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Вы можете получить строки, которые вам нужны, только с помощью оконных функций:

select tr.*
from (select tr.*,
             max(tr.dated) filter (where tr.grade <> tr.last_grade) over (partition by tr.studentID, tr.testID) as max_other_grade_date
      from (select tr.*,
                   first_value(tr.grade) over (partition by tr.studentID, tr.testID order by tr.dated desc) as last_grade
            from testresult tr
          ) tr
     ) tr
where max_other_grade_date is null or dated > max_other_grade_date ;

Простая агрегация получает желаемые дни:

select tr.studentID, tr.testID,
       max(dated) - min(dated)
from (select tr.*,
             max(tr.dated) filter (where tr.grade <> tr.last_grade) over (partition by tr.studentID, tr.testID) as max_other_grade_date
      from (select tr.*,
                   first_value(tr.grade) over (partition by tr.studentID, tr.testID order by tr.dated desc) as last_grade
            from testresult tr
          ) tr
     ) tr
where max_other_grade_date is null or dated > max_other_grade_date    
group by tr.studentID, tr.testID;

Здесь - это скрипта SQL.

0 голосов
/ 04 декабря 2018

Попробуйте что-то вроде этого:

SELECT t.StudentID, t.TestID, t.Grade, 
       min(t.Dated) as start_date, max(t.Dated) as last_date,
       max(t.Dated) - min(t.Dated) as how_many_days
FROM (
  SELECT * FROM TestResult
  WHERE StudentID = 1001 AND TestID=2001
  ORDER BY dated DESC LIMIT 1
) last_record
JOIN TestResult t
ON t.StudentID = last_record.StudentID
   AND t.TestID = last_record.TestID
   and t.Dated > (
     SELECT max( Dated ) FROM TestResult tt
     WHERE tt.StudentID = last_record.StudentID
       AND tt.TestID = last_record.TestID
       AND tt.Grade <> last_record.Grade
   )
GROUP BY t.StudentID, t.TestID, t.Grade

Демо: http://www.sqlfiddle.com/#!17/38beb/7

| studentid | testid | grade | start_date |  last_date | how_many_days |
|-----------|--------|-------|------------|------------|---------------|
|      1001 |   2001 |     A | 2018-11-23 | 2018-12-04 |            11 |

Чтобы сделать этот запрос быстрее, создайте многоколонный индекс:

CREATE INDEX some_name ON TestResult ( StudentID, TestID )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...