Как мне выбрать имена студентов, которые сдавали тест между 2 датами?

#sql #ms-access

#sql #ms-access

Вопрос:

Мне нужно показать студенческие удостоверения, которые сдавали тест как между 01/09/2007 — 31/12/2007, так и между 01/01/2008 — 20/06/2008. По какой-то причине это не работает. могу ли я получить от вас некоторую помощь? спасибо (текст ниже — это то, что я написал).

 SELECT studentId
FROM gradesTbl
WHERE testDate BETWEEN "01/09/2007" AND "31/12/2007" AND
WHERE testDate BETWEEN "01/01/2008" AND "20/06/2008";
  

Комментарии:

1. Удалите второе WHERE ключевое слово.

2. «между концом 2007 года» И «между началом 2008 года» … 😁

3. Поскольку эти два критерия фактически выполняются последовательно, вы можете просто использовать BETWEEN #01/09/2007# AND #20/06/2008# .

Ответ №1:

Вы можете сделать это с помощью EXISTS :

 SELECT DISTINCT g1.studentId
FROM gradesTbl AS g1
WHERE 
  EXISTS (SELECT 1 FROM gradesTbl AS g2 WHERE g2.studentId = g1.studentId AND  g2.testDate BETWEEN "01/09/2007" AND "31/12/2007")
  AND 
  EXISTS (SELECT 1 FROM gradesTbl AS g2 WHERE g2.studentId = g1.studentId AND  g2.testDate BETWEEN "01/01/2008" AND "20/06/2008");
  

Но было бы лучше выбрать из таблицы students , которая, как я полагаю, у вас есть, и studentId в gradesTbl ссылках ее id :

 SELECT s.studentId
FROM students AS s
WHERE 
  EXISTS (SELECT 1 FROM gradesTbl AS g WHERE g.studentId = s.studentId AND  g.testDate BETWEEN "01/09/2007" AND "31/12/2007")
  AND 
  EXISTS (SELECT 1 FROM gradesTbl AS g WHERE g.studentId = s.studentId AND  g.testDate BETWEEN "01/01/2008" AND "20/06/2008");
  

Примечание:
Даты в Access — это не текст, а дата-время:

 BETWEEN #2007/09/01# AND #2007/12/31#
BETWEEN #2008/01/01# AND #2008/06/20#
  

Комментарии:

1. Молодец, что правильно интерпретировал вопрос! Я внес небольшое редактирование, чтобы, надеюсь, устранить путаницу, которую оно создает.

Ответ №2:

Вы можете использовать агрегацию:

 SELECT studentId
FROM gradesTbl
GROUP BY studentId
HAVING SUM(IIF(testDate BETWEEN "01/09/2007" AND "31/12/2007", 1, 0) > 0 AND
       SUM(IIF(testDate BETWEEN "01/01/2008" AND "20/06/2008", 1, 0) > 0;
  

Каждое предложение в агрегации подсчитывает количество тестов, которые каждый учащийся проходит за указанный период. > 0 Возвращаются только учащиеся, которые прошли хотя бы один тест.

Ответ №3:

Вы также можете выполнить это, используя inner joins подзапросы on, например:

 select distinct t.studentid
from 
    (
        gradestbl t inner join
        (select distinct t.studentid from gradestbl t where t.testdate between #2007-09-01# and #2007-12-31#) q1
        on t.studentid = q1.studentid
    ) 
    inner join
    (select distinct t.studentid from gradestbl t where t.testdate between #2008-01-01# and #2008-06-20#) q2
    on t.studentid = q2.studentid
  

Ответ №4:

В Access разделителем дат является # знак.
Также логический оператор здесь должен быть OR .
Итак, правильный запрос

 SELECT studentId 
FROM gradesTbl
WHERE testDate BETWEEN #01/09/2007# AND #31/12/2007# 
OR testDate BETWEEN #01/01/2008# AND #20/06/2008#;
  

Поскольку оценка НИКОГДА не может отвечать обоим условиям, если вы хотите, чтобы учащиеся проходили тесты в оба периода, вам нужно будет сгруппировать свои данные.

 SELECT studentId, 
       sum(iif(testDate BETWEEN #01/09/2007# AND #31/12/2007#;1;0)) period1
       sum(iif(testDate BETWEEN #01/01/2008# AND #20/06/2008#;1;0)) period2
FROM gradesTbl
GROUP BY studentId
HAVING sum(iif(testDate BETWEEN #01/09/2007# AND #31/12/2007#;1;0)) > 0
   AND sum(iif(testDate BETWEEN #01/01/2008# AND #20/06/2008#;1;0)) > 0
  

Примечание: не проверено — возможно, вам придется заменить некоторые «;» на «,» в зависимости от ваших региональных настроек.

Комментарии:

1. Вопрос в следующем: «Мне нужно показать студенческие удостоверения, которые сдавали тест в период с 01/09/2007 по 31/12/2007 и с 01/01/2008 по 20/06/2008″

2. @forpas ты прав, плохо. Но я пока оставлю свой ответ как есть, на случай, если проблема плохо сформулирована 🙂 Я надеюсь, что OP прояснит