Solving Geek Problems

quinta-feira, julho 15, 2004

Non-trivial SQL problem...

Recentemente, deparei-me com um problema que, embora pareça trivial, a sua solução é tudo menos directa.
Imaginemos uma tabela de uma BD onde se encontram registados os items que cada utilizador de um site de comercio electrónico comprou ao longo do tempo.

eperson_id, item_id
-----------------------
1 1
1 2
2 1
3 1
3 2
3 3

A questão é tão simples como:
- Que utilizadores compraram o item 1 e 2?
Ou seja, imaginemos que todas as compras de um utilizador podem ser representadas por um cabaz. Eu quero saber que utilizadores possuem ambos os items (1 e 2) no seu cabaz (obviamente poderiam existir outros dentro do cabaz).

Para o exemplo apresentado a resposta seria:

eperson_id
----------------
1
3

Entrentanto já arranjei uma solução para o problema, mas não estou muito satisfeito, pois exige a realização de N+1 subqueries, sendo N o número de items a encontrar no cabaz.
Se conseguirem arranjar uma solução optimizada para este problema, agradecia que me enviassem o SQL correspondente.

Obrigado.

2 Comments:

  • As soluções encontradas até agora são:

    ------------------
    -- Rui Castro
    -- 3 queries
    ------------------
    SELECT DISTINCT eperson_id
    FROM bitstreamdownload
    WHERE eperson_id IN (SELECT eperson_id FROM bitstreamdownload WHERE item_id=17)
    AND eperson_id IN (SELECT eperson_id FROM bitstreamdownload WHERE item_id=35);


    --------------
    -- Cesar Ariza

    -- 2 queries
    --------------
    SELECT x.eperson_id
    FROM (SELECT DISTINCT eperson_id, item_id
    FROM bitstreamdownload
    WHERE item_id = 17 OR item_id = 35) AS x
    GROUP BY x.eperson_id HAVING count(x.item_id)>=2


    ---------------
    --Pedro Pereira
    -- 1 query
    ---------------
    SELECT bitstreamdownload.eperson_id
    FROM bitstreamdownload INNER JOIN bitstreamdownload as x ON bitstreamdownload.eperson_id=x.eperson_id
    GROUP BY bitstreamdownload.item_id, x.item_id, bitstreamdownload.eperson_id, x.eperson_id
    HAVING bitstreamdownload.item_id = 17 AND x.item_id=35


    PS: haverá maneira de testar a performance de cada uma?! há alguma ferramenta para isso!?

    By Blogger admin, at 15 de julho de 2004 às 16:06  

  • Nuno, essa solução não funciona.
    Se um comprador adquirir dois items 1 e nenhum item 2, irá aparecer na tua lista de resultados.

    By Blogger admin, at 24 de julho de 2004 às 15:02  

Enviar um comentário

<< Home