У меня проблема с фильтрацией в моем SQL. Пожалуйста, взгляните на схему базы данных.
Теперь я хотел бы получить программистов, которые знают PHP с навыками ●● / ●●● и Java с навыками ●●●. Я выполнил следующий запрос:
SELECT p.name, p.city FROM programmers p INNER JOIN skills s ON p.id = s.programmer WHERE ( s.lang = 'PHP' AND s.level > 1 ) OR ( s.lang = 'Java' AND s.level = 3 );
У меня есть
Но Кристофер не знает Java, но он возвращается. Замена OR
с помощью AND
между основными условиями не приводит к возврату ничего.
Более того, я хочу получить все навыки программиста в одной строке; здесь Джошуа находится в двух отдельных рядах. Как это исправить?
Все рассмотрено, последние вопросы. Как получить:
Надеюсь, это возможно. Заранее спасибо.
EDIT Операции, ориентированные на даты, не являются проблемой, и нет необходимости вычислять разницу между датами, SQL может содержать только год, то есть 2010 год. Обычно дата не является точкой.
Это пример проблемы с множеством наборов. Мне нравится решать их с помощью агрегации и having
:
SELECT p.name, p.city FROM programmers p INNER JOIN skills s ON p.id = s.programmer GROUP BY p.name, p.city HAVING SUM( s.lang = 'PHP' AND s.level > 1 ) > 0 AND SUM( s.lang = 'Java' AND s.level = 3 ) > 0;
РЕДАКТИРОВАТЬ:
Если вам нужен список навыков (который не был частью исходного вопроса), используйте group_concat()
:
SELECT p.name, p.city, group_concat(s.lang, ':', s.level separator '; '); FROM programmers p INNER JOIN skills s ON p.id = s.programmer GROUP BY p.name, p.city HAVING SUM( s.lang = 'PHP' AND s.level > 1 ) > 0 AND SUM( s.lang = 'Java' AND s.level = 3 ) > 0;
Это даст вам то, что вы хотите, но это совсем не гибко.
select p.name, p.city, php.lang, php.level, j.lang, j.level from programmer p join skills php on php.programmer = p.id join skills j on j.programmer = p.id where php.lang = 'PHP' and php.level > 1 and j.lang = 'Java' and j.level = 3;
Если вы будете делать много таких запросов, вы можете изучить создание каждого набора навыков:
create view JavaSkills as select programmer, lang, level, exp_from from skills where lang = 'Java'
Тогда запрос будет
select p.name, p.city, php.lang, php.level, j.lang, j.level from programmer p join PhpSkills php on php.programmer = p.id join JavaSkills j on j.programmer = p.id where php.level > 1 and j.level = 3;
План выполнения должен выглядеть аналогичным, если не идентичным, но запрос немного легче читать. Это также неудобно поддерживать, но каждый делает то, что можно. 😉