How to filter for a specific set of values in SQL, and only that specific set?
I have a problem with an inherited database for which the person who originally set it up left little documentation.
I have a set of users, each with three potential occupations. When queried, it returns values like these:
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 开发者_JAVA技巧 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
As you can see, for some reason, careers 1, 2, and 245 are set as defaults. Now, I want to filter out the users that have that specific set of careers, but not all instances of them, as any user could have legitimately chosen one or two of the set.
I can live with filtering out the odd character who just might have actually chosen that particular set on purpose.
Hope someone can help. I'm sure the solution is rather simple, but I can't come up with it.
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
)
Another solution:
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
)
The catch with the above solution is that it will exclude those that only have fewer than all three default careers. I.e., it will exclude users that only have (1,2), (1,245), (2,245), (1), (2), (245). If they must have all three and only those three, then you need to modify this solution like so:
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
)
Assuming you have a user table, career table, and a mapping table (user_career_map), then this will get you what you are looking for:
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;
I think this should identify the users who have careers 1, 2 and 245 listed:
SELECT User_ID
FROM Occupations
WHERE Career_ID IN (1, 2, 245)
GROUP BY Career_ID
HAVING COUNT(*) = 3
If you want the list of users who don't have that set of careers, then:
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)
精彩评论