Найти записи как И в MYSQL

Я хочу найти идентификатор студента, который должен иметь (professorId = 3 и CourseId = 4) и (professorId = 3 и CourseId = 2) и (professorId = 5 и CourseId = 8). иногда эта скобка равна одной или более 20

У меня есть два настольных класса и классы студентов, подобные этому:

Таблица студентовКлассы:

id | studentId | classId
1        1         2
2        1         3
3        1         4
4        2         3
5        2         5
6        3         2
7        4         3
8        4         2
9        1         8

Таблица классов:

id | professorId | CourseId

1        1            1
2        3            4
3        2            5
4        3            2
5        4            2
6        2            3
7        5            6
8        5            8
9        5            9

Было бы очень просто, если бы каждая скобка работала как или. Но я хочу найти ученика, у которого есть все эти вещи в виде и.

Этот запрос представляет собой сценарий «ИЛИ»:

select `studentsClasses`.`studentId` from `studentsClasses`
 inner join `class` on (`studentsClasses`.`classId`=`class`.`id` 
AND ((professorId = 3 And courseId = 4) OR (professorId = 3 And courseId = 2) 
   OR (professorId = 5 And courseId = 8)))

Но я хочу И такой сценарий:

select `studentsClasses`.`studentId` from `studentsClasses`
     inner join `class` on (`studentsClasses`.`classId`=`class`.`id` 
    AND ((professorId = 3 And courseId = 4) AND (professorId = 3 And courseId = 2) 
       AND (professorId = 5 And courseId = 8)))

Но приведенный выше запрос неверен.

Например, результат запроса с этим значением должен быть:

studentId
---------
1

Можете ли вы уточнить и показать желаемый результат? Кроме того, вам нужен общий запрос или конкретный, который точно соответствует AND ((professorId = 3 And courseId = 4) AND (professorId = 3 And courseId = 2) AND (professorId = 5 And courseId = 8))) критериям? Не уверен, каким должен быть результат, если у вас есть «иногда эта скобка равна одному или более 20».

mitkosoft 26.07.2024 19:38

Эти скобки можно изменить. например, когда вы устанавливаете флажок «Фильтры» @mitkosoft

farzad 26.07.2024 19:55
dbfiddle.uk/XrbiAbNh обратите внимание на разницу, если ученик посещает один и тот же урок несколько раз.
jarlh 29.07.2024 14:17
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
3
76
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Один из способов — использовать условие CASE WHEN и SUM над ним.

SELECT
  studentId,
  SUM(
    CASE
      WHEN c.professorId = 3 AND c.courseId = 4 THEN 1
      WHEN c.professorId = 3 AND c.courseId = 2 THEN 1
      WHEN c.professorId = 5 AND c.courseId = 8 THEN 1
      ELSE 0
    END) AS filter_cnt
FROM studentsClasses s
JOIN class c ON c.id = s.classId
GROUP BY 1
HAVING filter_cnt = 3

Другой способ — использовать отдельное соединение для каждого условия. Неэффективное решение, но может подойти, если данные не слишком велики.

WITH class_1 AS (
  SELECT DISTINCT studentId FROM studentsClasses s
  JOIN class c ON c.id = s.classId AND c.professorId = 3 AND c.courseId = 4
),

class_2 AS (
  SELECT DISTINCT studentId FROM studentsClasses s
  JOIN class c ON c.id = s.classId AND c.professorId = 3 AND c.courseId = 2
),

class_3 AS (
  SELECT DISTINCT studentId FROM studentsClasses s
  JOIN class c ON c.id = s.classId AND c.professorId = 5 AND c.courseId = 8
)

SELECT c1.studentId FROM class_1 c1
JOIN class_2 c2 ON c2.studentId = c1.studentId
JOIN class_3 c3 ON c3.studentId = c1.studentId

Спасибо @Климент Мерзляков. К сожалению, если я использую этот метод, из-за большого объема данных, а также большого количества соединений скорость запроса данных будет низкой, возможно, до 20 соединений.

farzad 26.07.2024 20:21

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

Kliment Merzlyakov 26.07.2024 20:24

Сколько у вас уникальных комбинаций proffesorId и courseId? Если он невелик, то можно попробовать что-нибудь со сводными таблицами.

Kliment Merzlyakov 26.07.2024 20:31

Я думаю около 1000 уникальных комбинаций. Однако, пожалуйста, предоставьте и этот метод. По крайней мере, если мне это не подходит, то подойдет и другим людям с меньшими данными.

farzad 26.07.2024 20:45

О, на самом деле решение с соединениями не работает

Kliment Merzlyakov 26.07.2024 21:11

Обновлено, решение с объединениями теперь должно работать.

Kliment Merzlyakov 26.07.2024 21:16

Хорошо, @farzad, я придумал другое решение — использовать CASE WHEN. Обновил ответ. Не могли бы вы это проверить?

Kliment Merzlyakov 26.07.2024 21:30

спасибо большое @Климент Мерзляков . Вы предложили замечательный метод.

farzad 27.07.2024 20:25

Просто сделайте GROUP BY. Используйте HAVING, чтобы убедиться, что присутствуют все три комбинации профессор/курс.

SELECT s.studentId
FROM studentsClasses s
    JOIN class c ON c.id = s.classId
WHERE (c.professorId = 3 AND c.courseId = 4)
   OR (c.professorId = 3 AND c.courseId = 2)
   OR (c.professorId = 5 AND c.courseId = 8)
GROUP BY s.studentId
HAVING COUNT(DISTINCT c.courseId) = 3

Благодаря COUNT(DISTINCT c.courseId) это будет работать, даже если ученик посещает один и тот же урок несколько раз.

Демо: https://dbfiddle.uk/XrbiAbNh (пролистните до конца).

Есть две таблицы, связанные идентификатором класса, студент не находится в той же таблице, что и профессор/курс.

MatBailie 26.07.2024 22:38

Сейчас обновлено. Присоединиться добавлено

jarlh 27.07.2024 22:14

Один из вариантов — использовать оператор IN для пары столбцов, группируя их по учащимся. HAVING Count() = Количество перечисленных пар — 3 в этом примере и до 20 или независимо от того, что это такое в вашем реальном контексте...

WITH    --  S a m p l e    D a t a :
  studentsClasses ( id, studentId, classId ) AS
    ( Select 1, 1, 2 Union All
      Select 2, 1, 3 Union All
      Select 3, 1, 4 Union All
      Select 4, 2, 3 Union All
      Select 5, 2, 5 Union All
      Select 6, 3, 2 Union All
      Select 7, 4, 3 Union All
      Select 8, 4, 2 Union All
      Select 9, 1, 8
    ),
  Class ( id, professorId, CourseId ) AS
    ( Select 1, 1, 1 Union All
      Select 2, 3, 4 Union All
      Select 3, 2, 5 Union All
      Select 4, 3, 2 Union All
      Select 5, 4, 2 Union All
      Select 6, 2, 3 Union All
      Select 7, 5, 6 Union All
      Select 8, 5, 8 Union All
      Select 9, 5, 9
    ) 
--    S Q L :
Select     s.studentId
From       studentsClasses s
Inner Join Class c ON c.id = s.classId
Where      (c.professorId, c.CourseId) IN( (3, 4), (3, 2), (5, 8) )
Group By   1
Having     Count(s.studentId) = 3  -- 3 is number of pairs matched
/*  R e s u l t :
studentId
---------
        1    */

См. скрипку здесь.

Другие вопросы по теме