2011-01-27 1 views
0

У меня проблема с унаследованной базой данных, для которой человек, который изначально настроил ее, оставил небольшую документацию.Как фильтровать определенный набор значений в SQL и только этот конкретный набор?

У меня есть набор пользователей, каждый из которых имеет три потенциальных профессии. При запросе, он возвращает значения, подобные этим:

USER_ID CAREER_ID TITLE 
1  44   Agricultural Engineer 
1  136   Educational Psychologist 
1  132   Clinical Psychologist 
18  245   3D Designer 
18  2   Accountant - Private Practice 
18  1   Accountant - Industry and Commerce 
19  245   3D Designer 
19  2   Accountant - Private Practice 
19  1   Accountant - Industry and Commerce 
20  128   Advice Centre Worker 
20  130   Careers Adviser 
20  129   Care Assistant 
21  1   Accountant - Industry and Commerce 
21  245   3D Designer 
21  2   Accountant - Private Practice 
23  245   3D Designer 
23  2   Accountant - Private Practice 
23  1   Accountant - Industry and Commerce 
29  245   3D Designer 
29  2   Accountant - Private Practice 
29  1   Accountant - Industry and Commerce 
30  219   PC Games Tester 
30  173   Bouncer 
30  103   Stunt Person 
32  245   3D Designer 
27  2   Accountant - Private Practice 
27  1   Accountant - Industry and Commerce 
27  245   3D Designer 
30  219   PC Games Tester 
30  173   Bouncer 
30  103   Stunt Person 

Как вы можете видеть, по какой-то причине, карьера 1, 2, и 245 устанавливаются по умолчанию. Теперь я хочу отфильтровать пользователей, у которых есть определенный набор карьеры, но не все их экземпляры, так как любой пользователь мог бы законно выбрать один или два набора.

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

Надеюсь, кто-то может помочь. Я уверен, что решение довольно простое, но я не могу придумать это.

+0

Какова структура таблицы для запроса выше? – Dan

+0

Оператор, которого вы требуете, известен как «реляционное подразделение» («номера поставщиков для поставщиков, которые поставляют все детали»). SQL не реализует это напрямую, вам нужно будет сворачивать свои собственные. Многие обычно используемые подходы обсуждаются здесь: http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/ – onedaywhen

+2

* Как вы можете видеть, по какой-то причине, карьеры 1, 2 и 245 установлены как значения по умолчанию * - Ну, я действительно не вижу, что делает 1, 2 и 245 отличными от 173 или 219. –

ответ

1
Select ... 
From Occupations O 
Where Not Exists (
        Select 1 
        From Occupations O1 
        Where O1.Career_Id In(1,2,245) 
         And O1.User_Id = O.User_Id 
        Group By O1.User_Id 
        Having Count(*) = 3 
        ) 

Другое решение:

Select ... 
From Occupations O 
Where Exists (
       Select 1 
       From Occupations O1 
       Where O1.Career_Id Not In(1,2,245) 
        And O1.User_Id = O.User_Id 
       ) 

Уловка с вышеупомянутым решением заключается в том, что она исключает те, у которых только меньше, чем все три карьеры по умолчанию. I.e., исключить пользователей, что только имеют (1,2), (1,245), (2,245), (1), (2), (245). Если они должны иметь все три, и только те три, то вам нужно изменить это решение так:

Select ... 
From Occupations O 
Where Exists (
       Select 1 
       From Occupations O1 
       Where O1.Career_Id Not In(1,2,245) 
        And O1.User_Id = O.User_Id 
       ) 
Or Exists (
      Select 1 
      From Occupations O2 
      Where O2.User_Id = O.User_Id 
      Having Count(*) < 3 
      ) 
+0

Не отвечает ли ваш ответ на набор пользователей? –

+0

@ Джонатан Леффлер - «Я хочу отфильтровать пользователей, у которых есть определенный набор карьеры». Мне сказано, что он хочет вернуть всех, кроме тех, у кого только 1,2,245. Поэтому я думаю, что это то, что нужно искать. – Thomas

+0

ОК - да, я полагаю, что «фильтр» может означать это. Я интерпретировал это наоборот, но теперь я не уверен, почему. –

0

Я думаю, что это должно идентифицировать пользователей, которые имеют карьеры 1, 2 и 245 в списке:

SELECT User_ID 
    FROM Occupations 
WHERE Career_ID IN (1, 2, 245) 
GROUP BY Career_ID 
HAVING COUNT(*) = 3 

Если вы хотите, чтобы список пользователей, которые не имеют такой набор карьеры, то:

SELECT User_ID 
    FROM Occupations 
WHERE User_ID NOT IN 
     (SELECT User_ID 
      FROM Occupations 
     WHERE Career_ID IN (1, 2, 245) 
     GROUP BY Career_ID 
     HAVING COUNT(*) = 3) 
0

Если у вас есть пользовательский стол, карьеры таблицы и таблица отображения (user_career_map), то получит вы, что вы ищете:

SELECT user_id, career_id, title 
FROM (
    SELECT distinct m.user_id, m.career_id, c.title 
    , sum(case when m.career_id in (1, 2, 245) then 1 else 0 end) over (partition by  m.user_id) filter 
    FROM user_career_map m inner join career c on m.career_id = c.career_id 
) WHERE filter <> 3 
ORDER BY user_id, career_id;