Можно ли упростить этот запрос sql?

У меня есть следующие таблицы:
Person, {"Id", "Name", "LastName"}
Спорт, {"Id" "Name", "Type"}
SportsPerPerson, {"Id", "PersonId", "SportsId"}

По моему запросу я хочу получить все Лица, которые вытесняют определенный спорт, тогда как у меня есть только атрибут «Имя» в спорте. Чтобы получить правильные строки, я выяснил следующие запросы:

SELECT * FROM Person WHERE Person.Id in ( SELECT SportsPerPerson.PersonId FROM SportsPerPerson INNER JOIN Sports on SportsPerPerson.SportsId = Sports.Id WHERE Sports.Name = 'Tennis' ) AND Person.Id in ( SELECT SportsPerPerson.PersonId FROM SportsPerPerson INNER JOIN Sports on SportsPerPerson.SportsId = Sports.Id WHERE Sports.Name = 'Soccer' ) 

ИЛИ

 SELECT * FROM Person WHERE Id IN (SELECT PersonId FROM SportsPerPerson WHERE SportsId IN (SELECT Id FROM Sports WHERE Name = 'Tennis')) AND Id IN (SELECT PersonId FROM SportsPerPerson WHERE SportsId IN (SELECT Id FROM Sports WHERE Name = 'Soccer')) 

Теперь мой вопрос: нет ли более простого способа написать этот запрос? Использование только ИЛИ не будет работать, потому что мне нужен человек, который играет в «Теннис» и «Футбол». Но использование AND также не работает, потому что значения не находятся в одной строке.

Вы должны использовать два запроса в запросе:

 SELECT * FROM Person p INNER JOIN SportsPerPerson spp1 ON (p.PersonId = spp1.PersonId) INNER JOIN Sports s1 ON (s1.SportsIN = spp1.SportId) INNER JOIN SportsPerPerson spp2 ON (p.PersonId = spp2.PersonId) INNER JOIN Sports s2 ON (s2.SportId = spp2.SportId) WHERE s1.Name = 'Tennis' AND s2.Name='Soccer' 

Вы можете использовать другой JOIN чтобы избежать второго IN . Суб-выбор возвращает только тех лиц, которые играют в теннис и футбол:

 SELECT * FROM Person WHERE Person.Id IN ( SELECT spp1.PersonId FROM SportsPerPerson spp1 JOIN SportsPerPerson spp2 ON ( spp2.PersonId = spp1.PersonId ) JOIN Sports s1 on spp1.SportsId = s1.Id JOIN Sports s2 on spp2.SportsId = s2.Id WHERE s1.Name = 'Tennis' AND s2.Name = 'Soccer' ) 

Хитрость заключается в использовании псевдонимов, так что вы можете использовать одни и те же таблицы несколько раз:

 SELECT p.* FROM Person p INNER JOIN SportsPerPerson spa ON p.Id = spa.PersonId INNER JOIN Sports sa ON spa.SportsId = sa.Id INNER JOIN SportsPerPerson spb ON p.Id = spb.PersonId INNER JOIN Sports sb ON spb.SportsId = sb.Id WHERE sa.Name = 'Tennis' AND sb.Name = 'Soccer' 

Эта:

 SELECT * FROM Person p WHERE ( SELECT COUNT(*) FROM Sports s JOIN SportsPerPerson sp ON sp.SportsID = s.id WHERE s.name IN ('Tennis', 'Soccer') AND sp.PersonID = p.id ) = 2 

или это:

 SELECT p.* FROM ( SELECT sp.PersonID FROM Sports s JOIN SportsPerPerson sp ON sp.SportsID = s.id WHERE s.name IN ('Tennis', 'Soccer') GROUP BY sp.PersonID HAVING COUNT(*) = 2 ) q JOIN person p ON p.id = q.personID 

Вам необходимо объявить UNIQUE KEY или PRIMARY KEY на SportsPerPerson (sportsid, personid) чтобы это работало правильно и быстро.