Inquiridor
Coluna com o saldo atual

Pergunta
-
Olá a todos, tenho uma tabela com os campos data e valor, preciso exibir o resultado com um coluna saldo, sendo este o valor da linha atual + a linha anterior.
Tentei com o codigo abaixo:
SELECT t1.data, t1.valor, (SELECT SUM(valor) FROM caixa AS t2 WHere t1.data >= t2.data ) AS saldo FROM caixa AS t1 ORDER BY data;
Se a tabela caixa possuir somente um registro por data funciona, a coluna saldo fica certa.Mas se existir mais de um registro com a mesma data não da certo, o valor da coluna saldo recebe o valor total da data.
Como posso resolver ?
sexta-feira, 23 de janeiro de 2009 03:52
Todas as Respostas
-
Olá Leandro, veja se o exemplo que criei no meu blog te ajuda:
http://emanuelmcdba.spaces.live.com/blog/cns!E634CAFF4AFF243D!683.entry
sexta-feira, 23 de janeiro de 2009 11:00 -
Olá Emanuel,
Muito interessante o seu exemplo!
Se me permite uma sugestão, você poderia adicionar uma coluna para armazenar a data valor do lançamento, e utilizar essa data (ao invés do código) para fazer o cálculo e ordenação, para que refletisse mais a realidade, já que é muito comum inserirmos lançamentos em atraso (com datas retroativas) ou ainda, lançamentos futuros.
Abraços,
Caio Proiete
Caio Proiete
http://www.caioproiete.comsexta-feira, 23 de janeiro de 2009 12:55 -
Oi Caio, obrigado pela sugestão, concordo com vc.
Eu havia colocado esse exemplo em meu blog após ter ajudado alguem aqui no fórum com essa dúvida, naquele momento o cenário da pessoa era esse, mas irei melhorá-la após sua contribuíção.
Valeu.
sexta-feira, 23 de janeiro de 2009 13:23 -
Leandro,
SE você utilizar o SQL Server 2005, você pode utilizar uma funcionalidade chamada CTE. Eu peguei um exemplo em algum lugar (Não lembro onde... Se o autor estiver lendo este post, me perdoe por eu não citar a autoria...) que trata de tabela de preços de itens com o preço atual e o preço anterior (Você poderá facilmente modificar para sua necessidade)
Code SnippetCREATE
TABLE [dbo].[Itens]([ItemId] [int]
NOT NULL,[Item] [varchar]
(100) NOT NULL, CONSTRAINT [PK_Itens] PRIMARY KEY CLUSTERED(
[ItemId]
ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])
ON [PRIMARY]go
Insert into Itens (ItemID, Item) Values (1, 'Microcomputador Core 2 Duo')
go
CREATE
TABLE [dbo].[TabelaPrecos]([ItemId] [int]
NOT NULL,[DataInicial] [datetime]
NOT NULL,[Preco] [decimal]
(10, 2) NOT NULL, CONSTRAINT [PK_TabelaPrecos] PRIMARY KEY CLUSTERED(
[ItemId]
ASC,[DataInicial]
ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])
ON [PRIMARY]go
Insert Into TabelaPrecos (ItemId, DataInicial, Preco) Values (1, cast('2008-01-01' as datetime), 100)
Insert Into TabelaPrecos (ItemId, DataInicial, Preco) Values (1, cast('2008-02-01' as datetime), 110)
Insert Into TabelaPrecos (ItemId, DataInicial, Preco) Values (1, cast('2008-03-01' as datetime), 120)
go
CREATE
VIEW [dbo].[ComparaPreco] ASWITH
ComparaPreco AS(
SELECT
Itens.Item, TabelaPrecos.ItemId, TabelaPrecos.DataInicial, TabelaPrecos.Preco,ROW_NUMBER
() OVER (Partition BY TabelaPrecos.ItemId ORDER BY DataInicial) AS rownumFROM
Itens INNER JOIN TabelaPrecosON
Itens.ItemId = TabelaPrecos.ItemId)SELECT
RegistroAtual.ItemId, RegistroAtual.Item, RegistroAnterior.Preco AS PrecoAnterior, RegistroAtual.Preco AS PrecoAtual, RegistroAtual.DataInicial AS DataInicial, case when RegistroPosterior.DataInicial is null then cast('2999-12-31 23:59:59' as datetime) else dateadd(s, -1, RegistroPosterior.DataInicial) end AS DataFinalFROM
ComparaPreco RegistroAtualLEFT
JOIN ComparaPreco RegistroPosterior ON RegistroAtual.rownum = RegistroPosterior.rownum - 1 AND RegistroAtual.ItemId = RegistroPosterior.ItemIdLEFT
JOIN ComparaPreco RegistroAnterior ON RegistroAtual.rownum = RegistroAnterior.rownum + 1 AND RegistroAtual.ItemId = RegistroAnterior.ItemIdgo
Select * from ComparaPreco
go
sexta-feira, 23 de janeiro de 2009 13:37 -
Bom Dia,
Interessante o exemplo e interessante as colocações. Abordei essa questão com profundidade em um Webcast que ministrei conforme o link abaixo:
Dicas e Truques sobre consultas complexas no SQL Server
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!162.entry
Embora o link tenha um exemplo resumido, o Webcast trata esse assunto e os problemas comuns com mais detalhes. por hora seguem algumas soluções.
Code Snippet-- Cria a tabela
create
table #caixa (idlancamento int identity(1,1),data
smalldatetime, valor smallmoney)-- Insere os registros
insert
into #caixa (data, valor) values ('20090101',10.00)insert
into #caixa (data, valor) values ('20090102',15.00)insert
into #caixa (data, valor) values ('20090103',12.00)insert
into #caixa (data, valor) values ('20090104',13.00)insert
into #caixa (data, valor) values ('20090105',18.00)-- Calcula o saldo
select
data, valor, (select sum(valor) from #caixa as t2 where t1.data >= t2.data) as saldofrom
#caixa as t1 order by t1.data-- Se houver empate o código não funciona
insert
into #caixa (data, valor) values ('20090101',14.00)select
data, valor, (select sum(valor) from #caixa as t2 where t1.data >= t2.data) as saldofrom
#caixa as t1 order by t1.data-- O IDLancamento pode ser utilizado para desempatar (Tie Breaker)
select
data, valor, (select sum(valor) from #caixa as t2 where t1.data >= t2.data andt1
.idlancamento >= t2.idlancamento) as saldofrom
#caixa as t1 order by t1.data-- Caso não haja critério para desempatar (Tie Breaker)
-- Você pode criar um (ex: menor lançamento primeiro)
select
data, valor, (select sum(valor) from #caixa as t2 where t1.data >= t2.data andt1
.valor >= t2.valor) as saldofrom
#caixa as t1 order by t1.data, t1.valor[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
sexta-feira, 23 de janeiro de 2009 13:37 -
Olá Emanuel, analisei o código mas o problema que a minha tabela não tem o campo código e por este motivo não tenho uma ordem crescente que não se repete e por isso não obtive sucesso.
Caio, você comentou sobre criar uma coluna "data valor", esta seria a união da data com o valor do lançamento ? E se existir na mesma data lançamento com o mesmo valor ?
Gustavo, executei os código abaixo, mas não obtive sucesso
select data, valor,
(select sum(valor) from projetadojr as t2 where
t1.data >= t2.data) as saldo
from projetadojr as t1 order by t1.dataResultado
http://img204.imageshack.us/img204/9366/imagembf2.png
select data, valor,
(select sum(valor) from projetadojr as t2 where
t1.data >= t2.data and
t1.valor >= t2.valor) as saldo
from projetadojr as t1 order by t1.data, t1.valorResultado
http://img132.imageshack.us/img132/2798/imagem1at2.png
Como disse acima a tabela que estou efetuando o select não tem um campo código, mas tem um uma chave primaria composta por 3 campos.
Alguma dica retornar este campo saldo ?
sábado, 24 de janeiro de 2009 03:25 -
Olá Leandro,
Tente assim:
Code Snippetdeclare
@t table (data smalldatetime, valor smallmoney)insert
into @t values ('20071001',84000)insert
into @t values ('20071008',800)insert
into @t values ('20071008',200)insert
into @t values ('20071015',78500)insert
into @t values ('20071019',666.67)insert
into @t values ('20071022',200)insert
into @t values ('20071022',300)insert
into @t values ('20071022',675)insert
into @t values ('20071029',179.94)select
data, valor,(
select sum(valor) from @t as t2 wheret1
.data >= t2.data and t1.valor <= t2.valor) as saldofrom
@t as t1 order by t1.data[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
sábado, 24 de janeiro de 2009 10:37 -
Gustavo, deu certo em parte.
Se na mesma data não existir documentos com o mesmo valor da certo, mas se tiver valores iguais na mesma data não da certo.
segunda-feira, 26 de janeiro de 2009 23:25 -
Olá Leandro,
Sempre que existir uma situação de empate o código dará errado. É por isso que é preciso eleger algum critério de "desempate". Anterioremente se a data fosse a mesma "empatava" e o código dava errado. Adicionei o critério de "menor valor". Se a data e o valor forem iguais, então o critério de "menor valor" não será válido, pois, haverá dois valores iguais.
Qual seria o critério de desempate no seu caso ?
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
terça-feira, 27 de janeiro de 2009 02:39 -
Olá Gustavo, com esta explicação compreendi o que ocorre na select.
Nos exemplos que você passou tem um campo codigo, sendo este utilizado como desempate.
Na minha tabela não tem este campo, mas tenho a chave primaria, sendo que esta é composta de 5 campos (empresa, filial, emitente, serie, documento)
Tentei implementar o where com este campos mas não consegui o resultado esperado.
Da certo de usar estes campos como criterio de desempate ?
terça-feira, 27 de janeiro de 2009 14:45 -
Olá Leandro,
Seu SQL Server é 2005 ?
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
terça-feira, 27 de janeiro de 2009 15:48 -
Trabalho com sql server 2005, mas a tabela em questão esta em access.quarta-feira, 28 de janeiro de 2009 00:53
-
Olá Leandro,
No Access ? Agora complicou...
Só mesmo se você criar uma função utilizando módulos no Access para fazer esse cálculo. Não me vem em mente uma forma de fazer isso usando só SQL através do suporte do Access.
Posso mover a thread ?
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
quarta-feira, 28 de janeiro de 2009 11:44 -
Não precisa mover a thread, a tabela é pequena então vou fazer um select do período, gravar em um temporário com um id e utilizar a solução abaixo que você passou.
-- O IDLancamento pode ser utilizado para desempatar (Tie Breaker)
select data, valor,
(select sum(valor) from #caixa as t2 where t1.data >= t2.data and
t1.idlancamento >= t2.idlancamento) as saldo
from #caixa as t1 order by t1.data
Mas qual seria a solução proposta se a tabela em questão estivesse no Sql Server 2005 ?quarta-feira, 28 de janeiro de 2009 23:00