2011-01-27 2 views
0

J'ai un problème avec une base de données héritée pour laquelle la personne qui l'a initialement créée a laissé peu de documentation.Comment filtrer pour un ensemble spécifique de valeurs dans SQL, et seulement cet ensemble spécifique?

J'ai un ensemble d'utilisateurs, chacun avec trois professions potentielles. Lorsqu'il a été interrogé, il renvoie des valeurs comme celles-ci:

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 

Comme vous pouvez le voir, pour une raison quelconque, les carrières 1, 2, et 245 sont définies par défaut. Maintenant, je veux filtrer les utilisateurs qui ont ce jeu spécifique de carrières, mais pas toutes les instances d'entre eux, comme n'importe quel utilisateur aurait pu légitimement choisi un ou deux de l'ensemble.

Je peux vivre avec le fait de filtrer le caractère impair qui pourrait avoir choisi cet ensemble particulier exprès.

J'espère que quelqu'un peut vous aider. Je suis sûr que la solution est plutôt simple, mais je n'arrive pas à la trouver.

+0

Quelle est la structure de la table pour la requête ci-dessus? – Dan

+0

L'opérateur dont vous avez besoin est connu sous le nom de «division relationnelle» («numéros de fournisseur pour les fournisseurs qui fournissent toutes les pièces»). SQL ne l'implémente pas directement, vous aurez besoin de rouler le vôtre. Beaucoup d'approches couramment utilisées discutées ici: http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/ – onedaywhen

+2

* Comme vous pouvez le voir, pour une raison quelconque, les carrières 1, 2 et 245 sont définies comme valeurs par défaut * - Eh bien, je ne vois vraiment pas ce qui différencie 1, 2 et 245 de 173 ou 219. –

Répondre

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 
        ) 

Une autre 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 
       ) 

Le problème avec la solution ci-dessus est qu'il exclura ceux qui n'ont que moins de trois carrières par défaut. C'est-à-dire, il exclura les utilisateurs qui seulement ont (1,2), (1,245), (2,245), (1), (2), (245). S'ils doivent avoir tous les trois et seulement ces trois, alors vous devez modifier cette solution comme ceci:

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

Votre réponse ne donne-t-elle pas le complément de l'ensemble des utilisateurs recherchés? –

+0

@Jonathan Leffler - "Je veux filtrer les utilisateurs qui ont ce ensemble spécifique de carrières". Pour moi, il dit qu'il veut rendre tout le monde sauf ceux qui ont seulement 1,2,245. Je pense donc que le complément est ce qui est recherché. – Thomas

+0

OK - oui, je suppose que le 'filtre dehors' peut bien signifier cela. Je l'ai interprété dans l'autre sens, mais je ne sais pas pourquoi. –

0

Je pense que cela devrait identifier les utilisateurs qui ont des carrières 1, 2 et 245 énumérés:

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

Si vous voulez la liste des utilisateurs qui n'ont pas cet ensemble de carrières, puis:

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

En supposant que vous avez une table utilisateur, table de carrière, et une table de correspondance (user_career_map), alors cela se vous ce que vous cherchez:

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; 
Questions connexes