У меня есть следующий оператор PHP / MySQL:
$varTemp = mysqli_num_rows(mysqli_query($connect,"SELECT * FROM table WHERE
(Date1 BETWEEN '2017-10-01' AND '2017-10-31' AND marker = 'Post' AND grade1 > 224) OR
(Date2 BETWEEN '2017-10-01' AND '2017-10-31' AND marker = 'Post' AND grade2 > 224) OR
(Date3 BETWEEN '2017-10-01' AND '2017-10-31' AND marker = 'Post' AND grade3 > 224) OR
(Date4 BETWEEN '2017-10-01' AND '2017-10-31' AND marker = 'Post' AND grade4 > 224)"));
Прямо сейчас между операторами стоит OR. Я также пробовал UNION и +, но получаю тот же результат. Этот оператор ДОЛЖЕН возвращать 20 записей, но он дает мне только 18, потому что есть два человека, которые находятся в обоих операторах «Date1» и «Date2».
У меня такой вопрос: как мне изменить этот оператор, чтобы подсчитать эти повторяющиеся записи?
См .: Почему я должен предоставлять MCVE для того, что мне кажется очень простым запросом SQL? - хотя, как предполагает user3783243, проблема такого рода действительно свидетельствует о плохом дизайне.
Для каждого человека собирается до 4 дат, и каждой дате соответствует оценка. Что вы предлагаете в качестве альтернативного дизайна? [пожалуйста, не воспринимайте это как язвительный вопрос, мне интересно узнать, есть ли лучший способ сделать это]






Природа OR требует, чтобы запись учитывалась только один раз, независимо от того, сколько частей предложения WHERE совпадают. Если вы хотите дважды подсчитать записи, которые находятся в нескольких диапазонах, вы на правильном пути с UNION. Однако UNION по умолчанию удаляет дубликаты, что дает тот же результат, что и OR. В вашем случае вы, вероятно, захотите использовать UNION ALL, который аналогичен UNION, но не удаляет дубликаты.
У вас есть ошибка в вашей логике, чтобы получить результат, который вы ищете, вам нужно будет выполнить несколько запросов, при этом OR в вашем предложении WHERE просто говорит, что если это произойдет, поместите это в результат, это фильтр, поэтому он не изменять количество записей в таблице самостоятельно.
вам нужно будет сделать что-то вроде этого:
SELECT * FROM table WHERE SELECT * FROM table WHERE
(Date1 BETWEEN '2017-10-01' AND '2017-10-31' AND marker = 'Post' AND grade1 > 224)
UNION ALL
SELECT * FROM table WHERE SELECT * FROM table WHERE
(Date2 BETWEEN '2017-10-01' AND '2017-10-31' AND marker = 'Post' AND grade2 > 224)
и повторите для каждого из ваших «ИЛИ», вот как вы можете дублировать записи.
Обратите внимание, что ваш запрос функционально идентичен ...
SELECT *
FROM table
WHERE
( Date1 BETWEEN '2017-10-01' AND '2017-10-31'
OR Date2 BETWEEN '2017-10-01' AND '2017-10-31'
OR Date3 BETWEEN '2017-10-01' AND '2017-10-31'
OR Date4 BETWEEN '2017-10-01' AND '2017-10-31'
)
AND marker = 'Post'
AND 224 IN(grade1,grade2,grade3,grade4)
... но если бы у меня был такой запрос, я бы переделал свою таблицу.
Соединение
Date1иgrade1похоже на то, что дизайн БД, вероятно, следует пересмотреть. Может быть, эти столбцы семестровые? Если это так, я бы добавил семестровую колонку, тогда это можно было бы легко сделать с помощьюwhere date BETWEEN '2017-10-01' AND '2017-10-31' AND marker = 'Post' AND grade > 244 and semester between 1 and 4.