правильный синтаксис для запроса sql и альтернатива WHERE EXISTS

Я хочу написать следующий запрос, чтобы вернуть все вакансии из таблицы вакансий, где пара профессия и подпрофессия равна одной из пар профессия и подпрофессия для определенного пользователя (одна из 4 пар). если у пользователя есть пара, где подпрофессия = 0, это означает взять все подпрофессии для соответствующей профессии:

что-то вроде этого:

select * from jobs j
where 
      (j.profession, j.subprofession) in 

      (select (u.profession1, u.subprofession1) from users u where userid=@userid),
       select (u.profession2, u.subprofession2) from users u where userid=@userid),
       select (u.profession3, u.subprofession3) from users u where userid=@userid),
       select (u.profession4, u.subprofession4) from users u where userid=@userid)
and
j.profession in (select u.profession1, u.profession2, u.profession3, u.profession4 from users u where userid=@userid) and (u.subprofession1 = 0 or u.subprofession2 = 0 or u.subprofession3 = 0 or u.subprofession4 = 0))

Я знаю, что этот запрос синтаксически неверен и не делает того, что должен, так как же можно достичь вышеуказанной цели, используя предложение IN или WHERE EXISTS?

jobs: profession, subprofession 
1      (100,        200)
2      (100,        300)
3      (100,        400)
4      (100,        500)
5      (200,        300)
6      (400,        500)
7      (400,        100)
8      (400,        600)
9      (200,        200)
10     (600,        700)
11     (100,        100)
12     (500,        300)
13     (200,        200)

users: (prof1, subprof1, prof2, subprof2, prof3, subprof3, prof4, subprof4)
1       (100,   100,      757,   646,      100,   0,        500,   400)
2       (100,   2,        565,   76,       567,   534,      433,   565)
3       (200,   454,      553,   345,      354,   435,      334,   877)
4       (500,   300,      456,   565,      354,   435,      545,   435)
5       (400,   453,      434,   453,      423,   234,      324,   4435)
6       (100,   400,      435,   543,      465,   654,      454,   543)
7       (435,   435,      600,   700,      100,   0,        500,   400)
8       (100,   100,      553,   345,      100,   0,        500,   400)

запрошенный запрос будет возвращаться из строк таблицы заданий: 1,2,3,4,11

это строки, в которых значения профессии и подпрофессии (в виде пары) появляются в одной из пар пользователей prof и subprof. также, поскольку для пользователя 1 есть запись (проф3=100 и подпроф3=0), запрос должен вернуть все заказы, в которых профессия равна 100 (для всех подпрофессий).


person vobs    schedule 30.05.2013    source источник
comment
SQL – это всего лишь язык структурированных запросов — язык, используемый многими системами баз данных, но не являющийся продуктом базы данных... конкретно - поэтому нам действительно нужно знать, какую систему базы данных (и какую версию) вы используете (пожалуйста, обновите теги соответствующим образом)....   -  person marc_s    schedule 30.05.2013
comment
также было бы полезно иметь несколько примеров таблиц и ожидаемых результатов для запроса.   -  person Friederike    schedule 30.05.2013
comment
Это непонятно: if the user has a pair where the subprofession=0, that means take all the subprofessions for the respective profession   -  person Tim    schedule 30.05.2013
comment
Оказываете ли вы какое-либо влияние на структуру базы данных? Вы можете перенести связь между пользователем и профессией/подпрофессией в таблицы отношений (пользователь-профессия, пользователь-подпрофессия, профессия-подпрофессия). @Tim Если пользователь не указал подпрофессию (например, специализацию), то получите все рабочие места по профессии. В противном случае, я думаю, только те, которые соответствуют подпрофессии.   -  person hangy    schedule 30.05.2013
comment
OK: Верно ли это понимание: если у нас есть (100,100) в паре 1 и (100,0) в паре 3, мы не должны исключать рабочие места в профессии 100, которые требуют подпрофессии 100, потому что 0 в паре 3 является подстановочным знаком, означающим любую работу в указанная профессия; В этом случае пара3 имеет приоритет над парой1.   -  person Tim    schedule 30.05.2013


Ответы (2)


Это должно сработать для вас:

SELECT  *
FROM    Jobs
WHERE   EXISTS
        (   SELECT  1
            FROM    Users
            WHERE   Users.UserID = @UserID
            AND (   (Users.Profession1 = Jobs.Profession AND Users.SubProfession1 IN (Jobs.SubProfession, 0))
                OR  (Users.Profession2 = Jobs.Profession AND Users.SubProfession2 IN (Jobs.SubProfession, 0))
                OR  (Users.Profession3 = Jobs.Profession AND Users.SubProfession3 IN (Jobs.SubProfession, 0))
                OR  (Users.Profession4 = Jobs.Profession AND Users.SubProfession4 IN (Jobs.SubProfession, 0))
                )
        );

Пример скрипта SQL

ИЗМЕНИТЬ

Поскольку это SQL-сервер, вы можете использовать CROSS APPLY..VALUES для разворота данных, таким образом вы можете выполнить внутреннее соединение и установить, соответствует ли задание, потому что подпрофессия равна 0, или есть ли точное совпадение подпрофессии:

WITH UserProf AS
(   SELECT  DISTINCT
            Users.UserID,
            p.Profession,
            p.SubProfession
    FROM    Users
            CROSS APPLY
            (VALUES
                (Profession1, SubProfession1),
                (Profession2, SubProfession2),
                (Profession3, SubProfession3),
                (Profession4, SubProfession4)
            ) p (Profession, SubProfession)
    WHERE   Users.UserID = @UserID
)
SELECT  Jobs.*, 
        MatchType = CASE WHEN MIN(UserProf.SubProfession) = 0 THEN 'All Subprofession' ELSE 'Exact subprofession' END
FROM    Jobs
        INNER JOIN UserProf
            ON UserProf.Profession = Jobs.Profession
            AND UserProf.SubProfession IN (0, Jobs.SubProfession)
GROUP BY Jobs.JobID, Jobs.Profession, Jobs.SubProfession;

Пример SQL-Fiddle

person GarethD    schedule 30.05.2013
comment
будет ли работать первый запрос в среде MS Access, несмотря на использование ключевого слова exists? - person vobs; 30.05.2013
comment
Да, Access поддерживает EXISTS, поэтому первый запрос будет работать нормально. - person GarethD; 30.05.2013

Я бы скорее посмотрел на самодокументируемый запрос, написанный два года назад, чем на запрос, в котором мне нужно понять, что он делает. Конечно, что-то, что является загадкой для меня, может быть простым делом для кого-то другого.

Учитывая мощность нуля в ячейке подпрофессии, что означает «соответствие профессии, не беспокойтесь о подпрофессии», я бы подошел к запросу как к объединению двух наборов.

Набор 1 — это набор всех должностей, соответствующих профессиям пользователя, где подпрофессия = 0.
Набор 2 — это набор всех должностей, соответствующих паре профессия/подпрофессия пользователя.

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

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

Если вы хотите, каждое соединение может добавить столбец, указывающий MatchLevel, т. е. ProfessionOnly в первом наборе и Both во втором наборе, но тогда вы можете увидеть одну и ту же работу дважды, один раз для общего соответствия и один раз для конкретного соответствия.

person Tim    schedule 30.05.2013