В MariaDB, MINUS
операторът връща отделни редове от лявата входна заявка, които не са изведени от дясната входна заявка.
MINUS
операторът беше въведен в MariaDB 10.6.1 като синоним на EXCEPT
оператор за целите на съвместимостта с Oracle. Следователно можем да използваме MINUS
и EXCEPT
взаимозаменяемо (в MariaDB 10.6.1 и по-нови).
Открих обаче, че MINUS
Операторът работи само когато моят sql_mode = "oracle"
. Въпреки че това не е изрично споменато в документацията на MariaDB, то се подразбира в задачата за внедряване на MINUS
оператор в MariaDB.
Примерни данни
Да предположим, че имаме следните таблици:
SELECT * FROM Teachers;
SELECT * FROM Students;
Резултат:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | +-----------+-------------+ +-----------+-------------+ | StudentId | StudentName | +-----------+-------------+ | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | | 6 | Bill | +-----------+-------------+
Можем да използваме MINUS
оператор, за да върне учители, които също не са ученици.
Задаване на sql_mode
към Oracle
Преди да започнем да използваме MINUS
оператор, нека зададем нашия sql_mode
към oracle
:
SET sql_mode = "oracle";
Добре, сега можем да продължим и да използваме MINUS
оператор.
Пример за MINUS
SELECT TeacherName FROM Teachers
MINUS
SELECT StudentName FROM Students;
Резултат:
+-------------+ | TeacherName | +-------------+ | Ben | | Cathy | +-------------+
Така че получаваме само стойности, които се появяват в Teachers
таблица, която също не се показва в Students
маса.
По подразбиране той връща отделни редове, така че само един ред се връща за Cathy
, въпреки че има двама учители с това име. Можем да променим това поведение – повече за това по-късно.
Можем също да го превключим и да поставим Students
таблица вляво и Teachers
вдясно.
SELECT StudentName FROM Students
MINUS
SELECT TeacherName FROM Teachers;
Резултат:
+-------------+ | StudentName | +-------------+ | Faye | | Jet | | Spike | | Ein | +-------------+
Възможно е да получите същия резултат, без да използвате MINUS
(или EXCEPT
) оператор. Например, можем да пренапишем първия си пример на това:
SELECT
DISTINCT TeacherName
FROM Teachers t
WHERE NOT EXISTS (SELECT StudentName FROM Students s
WHERE t.TeacherName = s.StudentName);
Резултат:
+-------------+ | TeacherName | +-------------+ | Ben | | Cathy | +-------------+
Включване на дубликати
По подразбиране MINUS
оператор имплицитно прилага DISTINCT
операция. С други думи, той връща само различни стойности по подразбиране. Но можем да посочим MINUS ALL
за да включите дубликати в резултата:
SELECT TeacherName FROM Teachers
MINUS ALL
SELECT StudentName FROM Students;
Резултат:
+-------------+ | TeacherName | +-------------+ | Cathy | | Ben | | Cathy | | Bill | +-------------+
Този път получихме четири реда, вместо двата, които получихме в първия ни пример.
Можем да видим, че и двете Кати бяха върнати вместо само една, както в първия ни пример.
Колкото до Бил? Има два законопроекта в Teachers
таблица, но тук се връща само една. Това вероятно е защото има един законопроект в Students
таблица, която би изключила един от законопроектите от нашите резултати.
И ето пример, който изрично използва DISTINCT
оператор:
SELECT TeacherName FROM Teachers
MINUS DISTINCT
SELECT StudentName FROM Students;
Резултат:
+-------------+ | TeacherName | +-------------+ | Ben | | Cathy | +-------------+
Както се очакваше, получаваме същия резултат, който бихме получили, ако премахнем DISTINCT
оператор.
Не сте в режим на Oracle?
Ето какво се случва, когато се опитаме да използваме MINUS
когато не е в режим на Oracle.
Нека нулираме нашия sql_mode
до настройката по подразбиране:
SET sql_mode = default;
Сега нека опитаме да използваме MINUS
оператор отново:
SELECT TeacherName FROM Teachers
MINUS
SELECT StudentName FROM Students;
Резултат:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT StudentName FROM Students' at line 3