SQL - Dúvida no desenvolvimento de uma query

14/10/2019

21

Sou iniciante em SQL, estou fazendo alguns exercícios, mas preciso de ajuda para responder um deles.

Tenho 3 tabelas (Clientes, Produtos, Pedidos) e preciso de uma query que responda a seguinte questão: Qual produto é o mais contratado na segunda compra do cliente?

Pra tentar ilustrar melhor tabelas estão da seguinte forma:
Tabela Cliente:(id, nome)
(1, José)
(2, Renato)
(3, Luciano)
(4, Gisele)
(5, Rafael)

Tabela Produtos: (id, descricao)
(1, ''Email Marketing'')
(2, ''Hospedagem'')
(3, ''Cloud'')

Tabela pedidos:
(id, cliente_id, produto_id, valor_mensal, data_inicio, data_fim)
(1, 1, 1, 50, 2/10/2017, null)
(2, 2, 2, 29, 3/15/2017, null)
(3, 2, 3, 159, 8/22/2016, 2/17/2017)
(4, 2, 3, 250, 2/17/2017, null)
(5, 2, 1, 50, 5/15/2015, null)
(6, 3, 1, 250, 5/1/2018, null)
(7, 3, 2, 59, 2/28/2018, null)
(8, 4, 2, 29, 11/8/2015, null)
(9, 4, 2, 35, 6/5/2016, null)
(10, 4, 2, 49, 6/7/2016, null)
(11, 5, 1, 50, 9/9/2016, 1/1/2018)
(12, 5, 3, 600, 9/15/2016, null)
Responder

Post mais votado

16/10/2019

Agora sim, isto é uma dúvida!
Você tem um código e não sabe como concluir ou resolver.
A função MAX() vai diretamente para o maior valor, então se quiser o produto mais vendido terá que usar outra abordagem.
Você vai precisar saber qual é o primeiro pedido, e identifica a partir deste ponto .
SELECT produtos.descricao AS ''Produto'', MAX(p2.produto_id) AS ''Quantidade''
FROM pedidos JOIN produtos
ON produtos.id = pedidos.produto_id
JOIN pedidos p2
ON produtos.id = p2.produto_id
WHERE p2.produto_id = pedidos.produto_id and pedidos.id>min(pedidos.id) ;

E tem que colocar o cliente, já que resultado é por cliente
Estou sem condições de testar....


Bruno

Entendi, mas você está querendo a resposta.
Bom para isto você terá que se dedicar um pouco mais.
A resposta está presente na sua lista (fato), então analise que irá solucionar.

Bons estudos para você.





Estou me dedicando. Só que como disse, estou com dificuldade nesse exercício especificamente, outros eu consegui.

Exemplo, a única coisa que consegui listar foi o serviço mais contratado no primeiro pedido, usando:

SELECT produtos.descricao AS ''Produto'', MAX(p2.produto_id) AS ''Quantidade''
FROM pedidos JOIN produtos
ON produtos.id = pedidos.produto_id
JOIN pedidos p2
ON produtos.id = p2.produto_id
WHERE p2.produto_id = pedidos.produto_id;

Não estou conseguindo fazer isso pra me retornar o produto mais vendido a partir do 2º pedido. Perguntei aqui justamente pra ter a resposta e justamente com ela ver a lógica e onde estou errando pra aprender e fazer nas próximas.

Obrigado!
Responder

Mais Posts

16/10/2019

Luiz Vichiatto

Bruno

Entendi, mas você está querendo a resposta.
Bom para isto você terá que se dedicar um pouco mais.
A resposta está presente na sua lista (fato), então analise que irá solucionar.

Bons estudos para você.



Responder

16/10/2019

Bruno Feitosa

Bruno

Entendi, mas você está querendo a resposta.
Bom para isto você terá que se dedicar um pouco mais.
A resposta está presente na sua lista (fato), então analise que irá solucionar.

Bons estudos para você.





Estou me dedicando. Só que como disse, estou com dificuldade nesse exercício especificamente, outros eu consegui.

Exemplo, a única coisa que consegui listar foi o serviço mais contratado no primeiro pedido, usando:

SELECT produtos.descricao AS 'Produto', MAX(p2.produto_id) AS 'Quantidade'
FROM pedidos JOIN produtos
ON produtos.id = pedidos.produto_id
JOIN pedidos p2
ON produtos.id = p2.produto_id
WHERE p2.produto_id = pedidos.produto_id;

Não estou conseguindo fazer isso pra me retornar o produto mais vendido a partir do 2º pedido. Perguntei aqui justamente pra ter a resposta e justamente com ela ver a lógica e onde estou errando pra aprender e fazer nas próximas.

Obrigado!
Responder
Qual produto é o mais contratado na segunda compra do cliente?

Na segunda compra ou a partir da segunda compra?
Responder

16/10/2019

Bruno Feitosa

Qual produto é o mais contratado na segunda compra do cliente?

Na segunda compra ou a partir da segunda compra?


Pelo enunciado, é só na segunda compra, mas de qualquer forma to tentando fazer para os 2 casos.

Os resultados teriam que ser:

Na segunda compra:
Hospedagem | 2
Cloud | 2

A partir da segunda compra:
Hospedagem | 3
Cloud | 3

Eu tentei isso para o caso de 'a partir da segunda compra' :
SELECT produtos.descricao AS 'Produto', MAX(pedidos.produto_id) AS 'Quantidade'
FROM pedidos JOIN produtos
ON produtos.id = pedidos.produto_id
JOIN pedidos p2
ON p2.id <> pedidos.id;

Mas ele só retorna o registro Hospedagem | 3, sendo que o Cloud tem a mesma quantidade de contratações.
Responder
produtos mais vendidos a partir da segunda compra:
SELECT
	pr.id,
	pr.descricao
FROM
	b_feitosa_produtos pr
JOIN
	b_feitosa_pedidos p on p.produto_id = pr.id
WHERE
	p.id > (select min(p2.id) primeira
			from b_feitosa_pedidos p2
			where p2.cliente_id = p.cliente_id )
GROUP BY
	pr.id,
	pr.descricao
HAVING
	count(pr.id) = (select top 1 count(*)
					from b_feitosa_pedidos p2
					where p2.id > (	select min(p3.id) primeira
									from b_feitosa_pedidos p3
									where p3.cliente_id = p2.cliente_id )
					group by p2.produto_id
					order by count(*) desc)

produtos mais vendidos a partir da segunda compra do cliente:
SELECT
	p.cliente_id, c.nome,
	p.produto_id, pr.descricao,
	sum(p.valor_mensal) valor
FROM
	b_feitosa_pedidos p
JOIN
	b_feitosa_cliente c ON c.id = p.cliente_id
JOIN
	b_feitosa_produtos pr ON pr.id = p.produto_id
WHERE
	p.id > (select min(p3.id) primeira
			from b_feitosa_pedidos p3
			where p3.cliente_id = p.cliente_id )
	and p.produto_id = 
		(select top 1 p3.produto_id maisvendido
		from b_feitosa_pedidos p3
		where p3.cliente_id = p.cliente_id
			and p3.id > (	select min(p4.id) primeira
							from b_feitosa_pedidos p4
							where p4.cliente_id = p3.cliente_id )
		group by p3.produto_id
		order by count(*) desc)
group by
	p.cliente_id, c.nome,
	p.produto_id, pr.descricao
order by
	p.cliente_id
Responder

20/10/2019

Bruno Feitosa

Sou iniciante em SQL, estou fazendo alguns exercícios, mas preciso de ajuda para responder um deles.

Tenho 3 tabelas (Clientes, Produtos, Pedidos) e preciso de uma query que responda a seguinte questão: Qual produto é o mais contratado na segunda compra do cliente?

Pra tentar ilustrar melhor tabelas estão da seguinte forma:
Tabela Cliente:(id, nome)
(1, José)
(2, Renato)
(3, Luciano)
(4, Gisele)
(5, Rafael)

Tabela Produtos: (id, descricao)
(1, ''''Email Marketing'''')
(2, ''''Hospedagem'''')
(3, ''''Cloud'''')

Tabela pedidos:
(id, cliente_id, produto_id, valor_mensal, data_inicio, data_fim)
(1, 1, 1, 50, 2/10/2017, null)
(2, 2, 2, 29, 3/15/2017, null)
(3, 2, 3, 159, 8/22/2016, 2/17/2017)
(4, 2, 3, 250, 2/17/2017, null)
(5, 2, 1, 50, 5/15/2015, null)
(6, 3, 1, 250, 5/1/2018, null)
(7, 3, 2, 59, 2/28/2018, null)
(8, 4, 2, 29, 11/8/2015, null)
(9, 4, 2, 35, 6/5/2016, null)
(10, 4, 2, 49, 6/7/2016, null)
(11, 5, 1, 50, 9/9/2016, 1/1/2018)
(12, 5, 3, 600, 9/15/2016, null)


Vim só agradecer a ajuda de vocês! Com as dicas daqui e com algumas outras que fui pegando em outros lugares, fiz dessa forma e deu certo:

SELECT DISTINCT
*
FROM
(
SELECT
pr.descricao Produto
, ROW_NUMBER() OVER(PARTITION BY p.cliente_id ORDER BY p.data_inicio) Quantidade
FROM
pedidos p
JOIN
clientes c
ON p.cliente_id = c.id
JOIN
produtos pr
ON p.produto_id = pr.id
) X
WHERE
Quantidade = 2;

Mais uma vez, obrigado pela ajuda!
Responder
Vim só agradecer a ajuda de vocês! Com as dicas daqui e com algumas outras que fui pegando em outros lugares, fiz dessa forma e deu certo:

SELECT DISTINCT
*
FROM
(
SELECT
pr.descricao Produto
, ROW_NUMBER() OVER(PARTITION BY p.cliente_id ORDER BY p.data_inicio) Quantidade
FROM
pedidos p
JOIN
clientes c
ON p.cliente_id = c.id
JOIN
produtos pr
ON p.produto_id = pr.id
) X
WHERE
Quantidade = 2;

A forma acima funciona mesmo?
Além de você não estar pegando a quantidade (está pegando o número da linha), está pegando uma "quantidade" indicada por você.
Responder

20/10/2019

Bruno Feitosa

Vim só agradecer a ajuda de vocês! Com as dicas daqui e com algumas outras que fui pegando em outros lugares, fiz dessa forma e deu certo:

SELECT DISTINCT
*
FROM
(
SELECT
pr.descricao Produto
, ROW_NUMBER() OVER(PARTITION BY p.cliente_id ORDER BY p.data_inicio) Quantidade
FROM
pedidos p
JOIN
clientes c
ON p.cliente_id = c.id
JOIN
produtos pr
ON p.produto_id = pr.id
) X
WHERE
Quantidade = 2;

A forma acima funciona mesmo?
Além de você não estar pegando a quantidade (está pegando o número da linha), está pegando uma "quantidade" indicada por você.


Nos testes que fiz, estava me retornando o resultado 'esperado'. Porém, levando em conta suas observações resolvi fazer novos testes, incluindo uma nova segunda compra que mudaria o resultado que deveria ser apresentado, mas realmente não funcionou.

O que tenho:
SELECT
*
FROM
(
SELECT
pr.descricao Produto
,ROW_NUMBER() OVER(PARTITION BY p.cliente_id ORDER BY p.id) XRANK
FROM
pedidos p
JOIN
clientes c
ON p.cliente_id = c.id
JOIN
produtos pr
ON p.produto_id = pr.id
) X
WHERE
XRANK = 2;

Usando essa query, consigo trazer todas as segundas compras de cada cliente, mas não encontrei uma forma de trazer somente o produto mais comprado.

Exemplo, com a tabela que tenho, são 3 Hospedagens e 2 Clouds vendidos na segunda compra. Isso a query acima me mostra. O que eu preciso é que ela mostre somente o produto que aparece mais vezes, nesse caso a hospedagem.
Responder
tentou assim, como eu havia postado acima?

produtos mais vendidos a partir da segunda compra:
SELECT
    pr.id,
    pr.descricao
FROM
    b_feitosa_produtos pr
JOIN
    b_feitosa_pedidos p on p.produto_id = pr.id
WHERE
    p.id > (select min(p2.id) primeira
            from b_feitosa_pedidos p2
            where p2.cliente_id = p.cliente_id )
GROUP BY
    pr.id,
    pr.descricao
HAVING
    count(pr.id) = (select top 1 count(*)
                    from b_feitosa_pedidos p2
                    where p2.id > (  select min(p3.id) primeira
                                    from b_feitosa_pedidos p3
                                    where p3.cliente_id = p2.cliente_id )
                    group by p2.produto_id
                    order by count(*) desc)

produtos mais vendidos a partir da segunda compra do cliente:
SELECT
    p.cliente_id, c.nome,
    p.produto_id, pr.descricao,
    sum(p.valor_mensal) valor
FROM
    b_feitosa_pedidos p
JOIN
    b_feitosa_cliente c ON c.id = p.cliente_id
JOIN
    b_feitosa_produtos pr ON pr.id = p.produto_id
WHERE
    p.id > (select min(p3.id) primeira
            from b_feitosa_pedidos p3
            where p3.cliente_id = p.cliente_id )
    and p.produto_id = 
        (select top 1 p3.produto_id maisvendido
        from b_feitosa_pedidos p3
        where p3.cliente_id = p.cliente_id
            and p3.id > (    select min(p4.id) primeira
                            from b_feitosa_pedidos p4
                            where p4.cliente_id = p3.cliente_id )
        group by p3.produto_id
        order by count(*) desc)
group by
    p.cliente_id, c.nome,
    p.produto_id, pr.descricao
order by
    p.cliente_id
Responder

22/10/2019

Bruno Feitosa

tentou assim, como eu havia postado acima?

produtos mais vendidos a partir da segunda compra:
SELECT
    pr.id,
    pr.descricao
FROM
    b_feitosa_produtos pr
JOIN
    b_feitosa_pedidos p on p.produto_id = pr.id
WHERE
    p.id > (select min(p2.id) primeira
            from b_feitosa_pedidos p2
            where p2.cliente_id = p.cliente_id )
GROUP BY
    pr.id,
    pr.descricao
HAVING
    count(pr.id) = (select top 1 count(*)
                    from b_feitosa_pedidos p2
                    where p2.id > (  select min(p3.id) primeira
                                    from b_feitosa_pedidos p3
                                    where p3.cliente_id = p2.cliente_id )
                    group by p2.produto_id
                    order by count(*) desc)

produtos mais vendidos a partir da segunda compra do cliente:
SELECT
    p.cliente_id, c.nome,
    p.produto_id, pr.descricao,
    sum(p.valor_mensal) valor
FROM
    b_feitosa_pedidos p
JOIN
    b_feitosa_cliente c ON c.id = p.cliente_id
JOIN
    b_feitosa_produtos pr ON pr.id = p.produto_id
WHERE
    p.id > (select min(p3.id) primeira
            from b_feitosa_pedidos p3
            where p3.cliente_id = p.cliente_id )
    and p.produto_id = 
        (select top 1 p3.produto_id maisvendido
        from b_feitosa_pedidos p3
        where p3.cliente_id = p.cliente_id
            and p3.id > (    select min(p4.id) primeira
                            from b_feitosa_pedidos p4
                            where p4.cliente_id = p3.cliente_id )
        group by p3.produto_id
        order by count(*) desc)
group by
    p.cliente_id, c.nome,
    p.produto_id, pr.descricao
order by
    p.cliente_id


Tentei sim, mas em ambos os casos está apresentando erro de sintaxe no MS SQL Server 2017 no uso do TOP. Já tentei corrigir, mas ainda não consegui, então não sei se deu certo.
Responder
publique a query que você executou e diz onde apresentou o erro.

Responder

22/10/2019

Bruno Feitosa

publique a query que você executou e diz onde apresentou o erro.



SELECT
p.cliente_id, c.nome,
p.produto_id, pr.descricao,
sum(p.valor_mensal) valor
FROM
pedidos p
JOIN
clientes c ON c.id = p.cliente_id
JOIN
produtos pr ON pr.id = p.produto_id
WHERE
p.id > (select min(p3.id) primeira
from pedidos p3
where p3.cliente_id = p.cliente_id)
and p.produto_id =
(select p3.produto_id, TOP 1 p3.produto_id maisvendido
from pedidos p3
where p3.cliente_id = p.cliente_id
and p3.id > ( select min(p4.id) primeira
from pedidos p4
where p4.cliente_id = p3.cliente_id )
group by p3.produto_id
order by count(*) desc)
group by
p.cliente_id, c.nome,
p.produto_id, pr.descricao
order by
p.cliente_id

Erro: Incorrect syntax near the keyword 'TOP'.
Responder
esta linha está errada:
select p3.produto_id, TOP 1 p3.produto_id maisvendido

o correto é:
select TOP 1 p3.produto_id maisvendido

Responder

22/10/2019

Bruno Feitosa

esta linha está errada:
select p3.produto_id, TOP 1 p3.produto_id maisvendido

o correto é:
select TOP 1 p3.produto_id maisvendido



Obrigado, Emerson! Arrumei e deu certo.

Acabei de testar a outra query que você havia mandado e ela era o que eu precisava!

SELECT
pr.descricao Produto
FROM
produtos pr
JOIN
pedidos p on p.produto_id = pr.id
WHERE
p.id > (select min(p2.id) primeira
from pedidos p2
where p2.cliente_id = p.cliente_id )
GROUP BY
pr.id,
pr.descricao
HAVING
count(pr.id) = (select top 1 count(*)
from pedidos p2
where p2.id > ( select min(p3.id) primeira
from pedidos p3
where p3.cliente_id = p2.cliente_id )
group by p2.produto_id
order by count(*) desc)

Fiz uns testes incluindos novos clientes e pedidos e tá tudo ok!

Minha última dúvida é se no Select, junto com o nome do produto (pr.descricao), eu consigo mostrar a quantidade de vezes que aquele produto foi comprado na segunda compra?
Responder
acrescente count(pr.id) na instrução;
SELECT
	pr.descricao Produto,
	count(pr.id) Qtd
FROM
[....]
Responder