Цикл SQL, условные запросы - PullRequest
0 голосов
/ 27 октября 2018

У меня есть таблица 'db', в которой есть следующие столбцы:

sname(student name)
cname (course name)
year ( the year when student take)
qtr ( the quarter when student take) : W , S, F (W>S>F)
grade

Что я хочу сделать, так это перечислить учащихся, которые увеличивали gpa с каждым кварталом (предыдущий класс <текущий gpa).У студентов могут быть промежутки между четвертями. </p>

SELECT a.sname 
FROM db a
WHERE EXISTS (SELECT * 
              FROM db b
              WHERE a.sname = b.sname 
                AND a.year = b.year 
                AND a.qtr < b.qtr 
                AND a.grade > b.grade)

UNION

После объединения я займусь делом when a.year > b.year.

Это то, что я делаю прямо сейчас - это правильный способ сделать этотаким образом?

Я понятия не имею, как я могу зацикливаться в запросах SQL ...

Любой совет будет признателен.Спасибо

1 Ответ

0 голосов
/ 27 октября 2018

Если вы используете текущую версию sqlite (3.25.X), это действительно легко сделать с помощью оконной функции lag() . Ниже я использую числовые значения для оценок вместо букв, потому что с ними гораздо проще работать, и предполагаю следующее определение таблицы (на основе вашего описания) и примеры строк в ней:

CREATE TABLE IF NOT EXISTS grades(
       sname TEXT NOT NULL
     , year INTEGER NOT NULL
     , qtr INTEGER NOT NULL
     , cname TEXT NOT NULL
     , grade NUMERIC
     , PRIMARY KEY (sname, year, qtr, cname)
) WITHOUT ROWID;
INSERT INTO grades(sname, cname, year, qtr, grade) VALUES
('Bob', 'Math', 2017, 3, 2.0), ('Bob', 'Math', 2017, 4, 2.5),
('Bob', 'Math', 2018, 1, 3.0), ('Amy', 'Math', 2017, 3, 4.0),
('Amy', 'Math', 2017, 4, 3.5), ('Amy', 'Math', 2018, 1, 4.0),
('Bob', 'History', 2017, 3, 3.5), ('Bob', 'History', 2017, 4, 3.0),
('Bob', 'History', 2018, 1, 3.5), ('Amy', 'History', 2017, 3, 2.5),
('Amy', 'History', 2017, 4, 3.5), ('Amy', 'History', 2018, 1, 4.0);

Я предполагаю, что, когда вы сказали предыдущий класс <текущий gpa </em>, вы имели в виду предыдущий gpa , чтобы соответствовать gpa, увеличивалось каждую квартал [sic] .

Во-первых, запрос, который вычисляет средний балл каждого студента за каждый квартал и включает в себя предыдущий средний балл в каждой строке (спасибо lag()):

SELECT sname, year, qtr
     , avg(grade) AS gpa
     , lag(avg(grade), 1, 0.0)
         OVER (PARTITION BY sname ORDER BY year, qtr) AS prev_gpa
FROM grades
GROUP BY sname, year, qtr
ORDER BY sname, year, qtr;

Это производит:

sname       year        qtr         gpa         prev_gpa  
----------  ----------  ----------  ----------  ----------
Amy         2017        3           3.25        0.0       
Amy         2017        4           3.5         3.25      
Amy         2018        1           4.0         3.5       
Bob         2017        3           2.75        0.0       
Bob         2017        4           2.75        2.75      
Bob         2018        1           3.25        2.75

Как видите, с этими примерами данных у Эми постоянно увеличивается средний балл, а у Боба - нет. Итак, вопрос в том, как отфильтровать результаты только для нее? Ответ на этот вопрос заключается в использовании HAVING с GROUP BY. Это немного усложняется тем, что значения, вычисленные оконными функциями, могут появляться только в списке столбцов выбора и предложениях ORDER BY, поэтому я вставляю приведенный выше запрос в CTE , чтобы обойти это ограничение:

WITH gpas AS (
  SELECT sname, year, qtr
       , avg(grade) AS gpa
       , lag(avg(grade), 1, 0.0)
           OVER (PARTITION BY sname ORDER BY year, qtr) AS prev_gpa
  FROM grades
  GROUP BY sname, year, qtr)
SELECT sname
FROM gpas
GROUP BY sname
HAVING sum(CASE WHEN gpa > prev_gpa THEN 1 ELSE 0 END) = count(gpa)
ORDER BY sname;

, который производит

sname     
----------
Amy       

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...