Dúvida em SQL, um desafio

9 respostas
A

Olá a todos,

Recentemente, me deparei com uma questão simples, básica, que vou exemplificar aqui:
Em um BD Minha_Locadora temos uma tabela Filmes, que para simplificação tem 2 atributos ID (chave artificial) e CUSTO (valor pago por aquele filme). Em outra Tabela Alugueis temos 4 atributos (simplificação): ID(chave artificial), ID_FILME (foreign key da tabela filme), VALOR_ALUGUEL (valor pago pelo filme) e DATA_ALUGUEL (auto explicativo).

Feito o cenário o que eu quero saber é: Qual a data em que a soma dos valores de alugueis passou o custo da fita? Ou seja, quanto tempo ela se paga.
Uma pergunta simples, mas eu matutei muito (não sou expert também) e no final acabei usando cursor. Só que ficaria inviável em análises grandes, é muito lento.

Minha pergunta é se tem como fazer este tipo de coisa sem usar cursores. Alguém sabe, já topou com isso?

Abraço!

9 Respostas

Andre_Fonseca

oi Abner,

Tenta fazer assim

SELECT max(a.data_aluguel) as data
FROM test.alugueis a
JOIN test.filmes b
ON a.id_filme = b.id;
HAVING COUNT(a.valor_aluguel) > b.custo

abs

Andre_Fonseca

oi Abner

Desculpe, testei aqui e isso que eu coloquei nao funciona

desconsidere :cry:

dmandrak

É inviável fazer uma nova coluna?

Pq se der, tipo uma coluna “se pagou”, vc roda um pequeno método que calcula se ela já se pagou ou não - se vc já está no lucro - e se sim, ele pega a última data de locação e armazena nessa coluna.

A

dmandrak:
É inviável fazer uma nova coluna?

Pq se der, tipo uma coluna “se pagou”, vc roda um pequeno método que calcula se ela já se pagou ou não - se vc já está no lucro - e se sim, ele pega a última data de locação e armazena nessa coluna.

Não é inviável não, porque era só uma modelagem, não cheguei a implementar. Na hora de modelar me pareceu bem natural conseguir essa informação, mas na hora de fazer o SQL…

Vou sugerir como questão da prova admissional de sql da empresa em que eu trabalho. Hehe, maldade.

Suponho que o mais simples seria mesmo fazer uma nova coluna e rodar um job periódico. Não existe soma condicional no sql até onde eu saiba… mas parece tão natural, deve ter várias perguntas do tipo “retorne a quantidade de registros que somados sejam = x”

Abraço

T

Cara…

Vc tem q somar todos os valores de determinada fita e comparar com o valor pago da fita…

Vou jah fazer uma consulta mais ou menos assim e posto…

PS: Tinha entendido errado… na verdade teria que fazer uma função pra verificar isso…

schistossoma

Buenas!

Tenta algo mais ou menos assim.

select case when sum(Alugueis.Valor_Aluguel) >= Filmes.Custo then max(Alugueis.Data_Aluguel) 
	        else 0 end, Alugueis.ID_Filme
from Alugueis
join Filmes on Filmes.ID = Alugueis.ID_Filme
group by Alugueis.ID_Filme, Alugueis.Valor_Aluguel

Não cheguei a testar aqui com essa modelagem de filmes e alugueis. Mas com uma estrutura mais ou menos parecida com essa deu certo. Se não rolar, fica mais simples deixar pra resolver no código mesmo. :slight_smile:

leoramos

Abner, acho que o solução do schistossoma funciona… testei aqui nesse modelo e aparentemente tá ok =)
(Coincidência é mato.)

Abraço!

O

Teste esta outra solução (testei no Oracle):

select f.id, sum(a.valor_aluguel), f.custo, max(a.data_aluguel) 
from filme f, aluguel a
where a.id_filme = f.id
group by f.id, f.custo
having sum(a.valor_aluguel) >= f.custo
A

Ficou tão interessante o post que eu modelei as tabelas para testar, com valores inteiros por preguiça:

CREATE TABLE alugueis ( 
	id           	int(11) NULL,
	id_filme    	int(11) NULL,
	valor_aluguel	int(11) NULL,
	data_aluguel 	datetime NULL,
	PRIMARY KEY(id)
)


ALTER TABLE `alugueis`
	ADD CONSTRAINT `fk_id_filmes`
	FOREIGN KEY(`id_filme`)
	REFERENCES `filmes`(`id`)
	
INSERT INTO alugueis(id, id_filme, valor_aluguel, data_aluguel) 
    VALUES(1, 1, 2, '2008-09-10 5:29:57.0')
GO
INSERT INTO alugueis(id, id_filme, valor_aluguel, data_aluguel) 
    VALUES(2, 1, 1, '2008-09-13 5:29:57.0')
GO
INSERT INTO alugueis(id, id_filme, valor_aluguel, data_aluguel) 
    VALUES(3, 1, 1, '2008-09-16 5:29:57.0')
GO
INSERT INTO alugueis(id, id_filme, valor_aluguel, data_aluguel) 
    VALUES(4, 1, 1, '2008-09-18 5:29:57.0')
GO
INSERT INTO alugueis(id, id_filme, valor_aluguel, data_aluguel) 
    VALUES(5, 1, 1, '2008-09-20 5:29:57.0')
GO
	
	
CREATE TABLE filmes ( 
    id   	int(11) NOT NULL DEFAULT '0',
    custo	int(11) NOT NULL,
    PRIMARY KEY(id)
)

INSERT INTO filmes(id, custo) 
    VALUES(1, 4)
GO

Reparem que no primeiro aluguel o valor de aluguel foi 2 (era lançamento). Depois todos alugueis foram a 1 real.
Então, a data que o filme começou a dar lucro foi em 2008-09-16…


oyama:
Teste esta outra solução (testei no Oracle):

select f.id, sum(a.valor_aluguel), f.custo, max(a.data_aluguel) from filme f, aluguel a where a.id_filme = f.id group by f.id, f.custo having sum(a.valor_aluguel) >= f.custo

Testei aqui e retorna o valor da data máxima… não funcionou.

o mesmo com

schistossoma:
Buenas!

Tenta algo mais ou menos assim.

select case when sum(Alugueis.Valor_Aluguel) >= Filmes.Custo then max(Alugueis.Data_Aluguel) 
	        else 0 end, Alugueis.ID_Filme
from Alugueis
join Filmes on Filmes.ID = Alugueis.ID_Filme
group by Alugueis.ID_Filme, Alugueis.Valor_Aluguel

Não cheguei a testar aqui com essa modelagem de filmes e alugueis. Mas com uma estrutura mais ou menos parecida com essa deu certo. Se não rolar, fica mais simples deixar pra resolver no código mesmo. :)

Estou decidido a mandar para meu professor de BD da facul e tirar o sono dele :twisted: .

Criado 3 de outubro de 2008
Ultima resposta 3 de out. de 2008
Respostas 9
Participantes 7