Pergunta

Selecione U.User, G.Group, U2G.Soming dos usuários, Grupos, U2G onde usuários.u = u2g.u e groups.g = u2g.g

que retorna dados como este:

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

Agora eu gostaria de limitar essa consulta de tal maneira que ela só mostra usuários que são Ambas Nos grupos 3 e 5 -, ele retornaria apenas {1,3, a}, {1,5, b} para meus dados de exemplo.

EDIT: Eu adicionei outra coluna aos dados, porque pode haver uma solução incorreta usando um grupo por.

Edit2: Desculpe, fui enganado pela documentação. O MySQL 4.0 não suporta subconsivos :(

Edit3: Este SQL será gerado programaticamente para qualquer número de grupos (bem, até 20 na especificação atual), então eu gostaria de evitar soluções que me dêem muita codificação adicional para fazer. Se uma solução não for encontrada, apenas modificarei o .NET 1.1 DATATABLE resultante, mas gostaria de evitar isso, se possível.

Edit4: Alguma nova ideia? Talvez um sem subconsERias que inclua em (3,5)?

Foi útil?

Solução

Usar a junta dupla com a Table Grupos fornecerá o resultado correto:

  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

No entanto, isso não corresponde exatamente à sua solicitação, que você deseja duas linhas, uma para cada grupo. Isso só lhe dará uma linha, você poderá se juntar a ela mais uma vez com grupos para renderizar duas linhas.

Outro exemplo (se você está selecionando usando o mesmo grupo com o qual mapeia):

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

Outras dicas

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

Algo nesse sentido?

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

Solução não general bastante horrível que resulta em duas linhas no 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)
           ;

Por que é groups usado na consulta? Seu único campo acessado (g) existe em u2g. Eu imagino que você provavelmente quer trazer de volta um monte de coisas de lá também.

Para obter o tipo de conjunto de resultados que você descreve sem o uso de subconsulta, você acaba com uma bagunça real: uma explosão quadrática de texto de consulta!

Você precisará de algo do seguinte formulário:

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

Como essa é uma consulta gerada programaticamente, usarei uma notação semelhante à script da web aqui para descrever a construção da consulta. Também farei a erupção cutânea e a suposição simplificadora injustificada de que os identificadores do grupo não são um potencial vetor de ataque de injeção de 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]%>
  <% } %>
<% } %>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top