Question

sélectionnez u.user, g.group, u2g.quelque chose     des utilisateurs, groupes, u2g     où utilisateurs.u = u2g.u et groupes.g = u2g.g

qui renvoie des données comme ceci:

user, group, something
----------------------
1   , 3,     a
1   , 5,     b
2   , 3,     c
3   , 3,     d
4   , 5,     e

maintenant, j'aimerais limiter cette requête de telle sorte qu'elle ne montre que les utilisateurs les deux des groupes 3 et 5, de sorte qu'elle ne renvoie que {1,3, a}, { 1,5, b} pour mes données d'exemple.

modifier: j'ai ajouté une autre colonne aux données car il est possible qu'une solution incorrecte utilise un groupe par.

edit2: désolé, la documentation m'a induit en erreur. MySQL 4.0 ne supporte pas les sous-requêtes: (

edit3: Ce code SQL sera généré par programme pour un nombre quelconque de groupes (jusqu'à 20 dans la spécification actuelle), aussi je voudrais éviter les solutions qui me donnent trop de codage supplémentaire à faire. Si aucune solution ne peut être trouvée, je modifierai simplement le DataTable .NET 1.1 résultant, mais je voudrais éviter cela si possible.

edit4: une nouvelle idée? Peut-être un sans sous-requêtes qui comprend IN (3,5)?

Était-ce utile?

La solution

L'utilisation de la double jointure avec groupes-table vous donnera le résultat correct:

  select u.user, u2g.something 
  from   users 
  INNER JOIN u2g ON users.u = u2g.u
  INNER JOIN groups g1 ON u2g.g = g1.g AND g1.group = 3
  INNER JOIN groups g2 ON u2g.g = g2.g AND g2.group = 5
  /* try this for two rows, one for each group */
  INNER JOIN groups ON u2g.g = groups.g

Toutefois, cela ne correspond pas exactement à votre demande, à savoir que vous souhaitiez deux lignes, une pour chaque groupe. Cela ne vous donnera qu'une ligne, vous pourrez peut-être la rejoindre une fois de plus avec des groupes pour rendre deux lignes.

Autre exemple (si vous sélectionnez le même groupe que celui sur lequel vous mappez):

SELECT u.uID, gm.something 
FROM cdcms_users u 
inner join cdcms_group_memberships gm1 on gm1.uID = u.uID AND gm1.gID = 32
inner join cdcms_group_memberships gm2 on gm2.uID = u.uID AND gm2.gID = 33

Autres conseils

select u.user, g.group, u2g.something 
from users u, groups g, u2g 
where u.user = u2g.user and g.group = u2g.group 
    where exists 
     (select 1 
         from u2g u2g2 
        where u2g2.user=u.user and u2g2.group in(3,5))

Quelque chose dans ce sens?

select u.[user], g.group
from     u
    inner join ug on ug.userid = u.id   
    inner join g on g.id = ug.groupid
    inner join 
    (
        select ug.userid
        from ug
        where ug.groupid in (1,2)
        group by ug.userid
        having count(*) = 2
    ) sub on sub.userid = u.id

-Edoode

Solution honteuse non générale générant deux lignes dans Oracle:

  select users.u, groups.g
    from   users , groups, u2g, groups g2, u2g u2g2
    where  users.u = u2g.u 
           and users.u = u2g2.u
           and groups.g = u2g.g
           and g2.g = u2g2.g
           and (groups.g in (3,5) and g2.g in (3,5) and groups.g <> g2.g)
           ;

Pourquoi groups est-il utilisé dans la requête? Son seul champ accessible (g) existe dans u2g. J'imagine que vous voulez probablement ramener un bateau rempli de choses à partir de là aussi.

Pour obtenir le type de résultat que vous décrivez sans utiliser de sous-requêtes, vous vous retrouvez face à un véritable gâchis: une explosion quadratique de texte de requête!

Vous aurez besoin de quelque chose de la forme suivante:

select users.u, groups.g, u2g0.something
from users u, groups g, u2g u2g0, u2g u2g1
where groups.g = 3
     and users.u = u2g0.u
     and u2g0.g = 3
     and users.u = u2g1.u
     and u2g1.g = 5
union all
select users.u, groups.g, u2g1.something
from users u, groups g, u2g u2g0, u2g u2g1
where groups.g = 5
     and users.u = u2g0.u
     and u2g0.g = 3
     and users.u = u2g1.u
     and u2g1.g = 5

Comme il s'agit d'une requête générée par programme, j'utiliserai ici une notation semblable à un script de page Web pour décrire la construction de la requête. Je ferai également l'hypothèse simpliste, irréfléchie et injustifiée, que les identificateurs de groupe ne sont pas un vecteur d'attaque potentiel par injection SQL. : -)

<% for(int i = 0; i < requiredGroups.Length; i++) { %>
  <% if(i > 0) { %>
    union all
  <% } %>
select users.u, groups.g, u2g<%=i%>.something
from users u, groups g
  <% for(int j = 0; j < requiredGroups.Length; j++) { %>
     , u2g u2g<%=j%>
  <% } %>
where groups.g = <%=requiredGroups[i]%>
  <% for(int j = 0; j < requiredGroups.Length; j++) { %>
     and users.u = u2g<%=j%>.u
     and u2g<%=j>.g = <%=requiredGroups[j]%>
  <% } %>
<% } %>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top