SQL complicada. Usando Data
Oi,
Preciso de uma sql que retorne o valor da ultima venda de cada cliente de cada dia.
No access fica assim:
select data, codcli, last(valor) as UltimaVenda
from vendas
where data<date-30
group by data, codcli
Porem no Firebird não existe o ´last´, teria algo semelhente?
:arrow: [color=red:c089737d5b]Título alterado por oTTo. Removido: ´me ajudem´.[/color:c089737d5b]
Preciso de uma sql que retorne o valor da ultima venda de cada cliente de cada dia.
No access fica assim:
select data, codcli, last(valor) as UltimaVenda
from vendas
where data<date-30
group by data, codcli
Porem no Firebird não existe o ´last´, teria algo semelhente?
:arrow: [color=red:c089737d5b]Título alterado por oTTo. Removido: ´me ajudem´.[/color:c089737d5b]
Larry
Curtidas 0
Respostas
Emerson Nascimento
12/01/2005
select data, codcli, max(valor) as UltimaVenda
from vendas
where data<date-30
group by data, codcli
from vendas
where data<date-30
group by data, codcli
GOSTEI 0
Larry
12/01/2005
select data, codcli, max(valor) as UltimaVenda
from vendas
where data<date-30
group by data, codcli
max(valor) irá pegar o maior valor do dia pro cliente, e eu quero o ultimo valor. Tem como?
GOSTEI 0
Thomaz_prg
12/01/2005
colega, não tenho certeza se irá funcionar, mas tente assim:
select data, codcli, (select last 1 valor from vendas b where b.codcli = a.codcli and b.data = a.data) as Ultima_Venda from vendas a where a.data<(select current_date from RDB$Database)-30
group by a.data, a.codcli
Poste aí se deu certo ou não.
select data, codcli, (select last 1 valor from vendas b where b.codcli = a.codcli and b.data = a.data) as Ultima_Venda from vendas a where a.data<(select current_date from RDB$Database)-30
group by a.data, a.codcli
Poste aí se deu certo ou não.
GOSTEI 0
Larry
12/01/2005
colega, não tenho certeza se irá funcionar, mas tente assim:
select data, codcli, (select last 1 valor from vendas b where b.codcli = a.codcli and b.data = a.data) as Ultima_Venda from vendas a where a.data<(select current_date from RDB$Database)-30
group by a.data, a.codcli
Poste aí se deu certo ou não.
Oi,
Testei on ibexpert e da erro no 1 e se remover o 1, da erro no last. Algo mais?
GOSTEI 0
Afarias
12/01/2005
não existe LAST ... existe FIRST (FIREBIRD APENAS!), então faça:
select first 1 valor from vendas
order by data desc
ordenando a data de forma descendente e pegando o 1º registro apenas, vc terá o último registro (na ordem de data)
T+
select first 1 valor from vendas
order by data desc
ordenando a data de forma descendente e pegando o 1º registro apenas, vc terá o último registro (na ordem de data)
T+
GOSTEI 0
Fsflorencio
12/01/2005
select DISTINCT data, codcli, ( SELECT VALOR FROM VENDAS V1
WHERE V1.COD_VENDA = (SELECT MAX(COD_VENDA) FROM VENDAS V2 WHERE V2.COD_CLI = V.COD_CLI AND V2.DATA = V.DATA) )
from vendas V
where data<date-30
//levando em conta que o código da venda é a chave primária com um número crescente
//tirei o group by pois não uso nenhuma função agregada no select principal, mas coloquei o distinct para não ocorrer repetição
//apelidei as tabelas de vendas como V, V1 e V2
resumo: estou agrupando a data e o código do cliente buscando o maior valor para aquele cliente daquele período, selecionando o maior código de venda daquela data e daquele cliente para buscar o valor da venda do código da venda encontrado
WHERE V1.COD_VENDA = (SELECT MAX(COD_VENDA) FROM VENDAS V2 WHERE V2.COD_CLI = V.COD_CLI AND V2.DATA = V.DATA) )
from vendas V
where data<date-30
//levando em conta que o código da venda é a chave primária com um número crescente
//tirei o group by pois não uso nenhuma função agregada no select principal, mas coloquei o distinct para não ocorrer repetição
//apelidei as tabelas de vendas como V, V1 e V2
resumo: estou agrupando a data e o código do cliente buscando o maior valor para aquele cliente daquele período, selecionando o maior código de venda daquela data e daquele cliente para buscar o valor da venda do código da venda encontrado
GOSTEI 0
Larry
12/01/2005
select DISTINCT data, codcli, ( SELECT VALOR FROM VENDAS V1
WHERE V1.COD_VENDA = (SELECT MAX(COD_VENDA) FROM VENDAS V2 WHERE V2.COD_CLI = V.COD_CLI AND V2.DATA = V.DATA) )
from vendas V
where data<date-30
//levando em conta que o código da venda é a chave primária com um número crescente
//tirei o group by pois não uso nenhuma função agregada no select principal, mas coloquei o distinct para não ocorrer repetição
//apelidei as tabelas de vendas como V, V1 e V2
resumo: estou agrupando a data e o código do cliente buscando o maior valor para aquele cliente daquele período, selecionando o maior código de venda daquela data e daquele cliente para buscar o valor da venda do código da venda encontrado
Oi,
Valeu pela força,
Funcionou perfeito, mas ficou muito lento para retornar os resultados quado os periodo (where data...) for muito grande, oque resulta em muitos registros - e são milhares.
Acabei fazendo de outra forma:
select data, codcli, max(cont) as Maior <- chave primaria
from vendas
where data>:d1
group by data, codcli
Então coloquei um campo calculado (valor_calc) que faz um oncalcfiled:
´select valor from vendas where cont = ´+dataset.fieldbyname(´maior´).asstring
Esta é a melhor solução ou tem algo melhor?
GOSTEI 0
Larry
12/01/2005
não existe LAST ... existe FIRST (FIREBIRD APENAS!), então faça:
select first 1 valor from vendas
order by data desc
ordenando a data de forma descendente e pegando o 1º registro apenas, vc terá o último registro (na ordem de data)
T+
Oi, valeu pela ajuda.
Cheguei a pensar nesta solução, mas me preocupei com:
Se eu fizer algo do tipo select valor from vendas where cont = 1500, o firebird valor me retornar apenas 1 registro instantaneamente.
Será que se eu fizer select first 1 from vendas order by data desc, o firebird não vai fazer algo como ´puxar´ todos os registro da tabela para colocar em ordem decrescente para retorna o primeiro registro, oque ficaria lento.
Me aparece que isso ocorre com o comando LIKE e UCASE ???
GOSTEI 0
Larry
12/01/2005
Outro detalhe, preciso do ultimo valor de cada dia de cada cliente, entao teria que ser algo do tipo:
select data, codcli, first 1 valor
from vendas
group by data, codcli
order by valor desc
Só que este sql não funciona. E ainda o resultado tem que ser em ordem de data crescente.
select data, codcli, first 1 valor
from vendas
group by data, codcli
order by valor desc
Só que este sql não funciona. E ainda o resultado tem que ser em ordem de data crescente.
GOSTEI 0
Emerson Nascimento
12/01/2005
como você informou que [i:2249a0a307]cont[/i:2249a0a307] é a chave primária, veja se assim funciona:
select v.data, v.codcli, v.valor
from vendas v
where v.cont in (select max(v2.cont) from vendas v2
                          where v2.data>:d1
                          group by v2.data, v2.codcli)
select v.data, v.codcli, v.valor
from vendas v
where v.cont in (select max(v2.cont) from vendas v2
                          where v2.data>:d1
                          group by v2.data, v2.codcli)
GOSTEI 0
Adilsond
12/01/2005
Vamos por partes. Partindo do princípio de que o campo data seja data/hora da venda:
Pegaremos primeiro a maior data/hora de um cliente específico e em um dia específico:
Agora com a data em mãos, pegaremos o maior valor por cliente:
Pegaremos primeiro a maior data/hora de um cliente específico e em um dia específico:
select max(v.data) from vendas v where v.codcli = xxxxx and cast(v.data as date) = xxxxx
Agora com a data em mãos, pegaremos o maior valor por cliente:
select v1.codcli, v1.data, v1.valor from vendas v1 where data = (select max(v2.data) from vendas v2 where v2.codcli = v1.codcli and cast(v2.data as date) = cast(v1.data as date)) order by v1.codcli, v1.data
GOSTEI 0
Emerson Nascimento
12/01/2005
então, Larry, a dica que eu te passei
[color=blue:06505f86fe][i:06505f86fe]select v.data, v.codcli, v.valor
from vendas v
where v.cont in (select max(v2.cont) from vendas v2
                          where v2.data>:d1
                          group by v2.data, v2.codcli)
order by v.data[/i:06505f86fe][/color:06505f86fe]
ou a de algum dos colegas funcionou? poste aqui a solução que você encontrou.
[color=blue:06505f86fe][i:06505f86fe]select v.data, v.codcli, v.valor
from vendas v
where v.cont in (select max(v2.cont) from vendas v2
                          where v2.data>:d1
                          group by v2.data, v2.codcli)
order by v.data[/i:06505f86fe][/color:06505f86fe]
ou a de algum dos colegas funcionou? poste aqui a solução que você encontrou.
GOSTEI 0
Larry
12/01/2005
então, Larry, a dica que eu te passei
[color=blue:bb84a26998][i:bb84a26998]select v.data, v.codcli, v.valor
from vendas v
where v.cont in (select max(v2.cont) from vendas v2
where v2.data>:d1
group by v2.data, v2.codcli)
order by v.data[/i:bb84a26998][/color:bb84a26998]
ou a de algum dos colegas funcionou? poste aqui a solução que você encontrou.
Valeu pela força Emerson,
Funcionou perfeito, mas acabou ficando lento tambem quando o periodo for grande, oque retorna muitos (milhares) de registros.
Até agora a forma mais rapida é a que fiz:
select data, codcli, max(cont) as Maior <- chave primaria
from vendas
where data>:d1
group by data, codcli
Então coloquei um campo calculado (valor_calc) que faz um oncalcfiled:
´select valor from vendas where cont = ´+dataset.fieldbyname(´maior´).asstring
Oque eu fiz é mais ou menos a mesma coisa que voce sugeriu, mas não sei exetamente porque, mas do jeito que eu fiz fica bem mais rapido.
Me parece que o trecho que voce sugeriu:
where v.cont in (select max(v2.cont) from vendas v2
where v2.data>:d1
group by v2.data, v2.codcli)
o firebird torna muito lento, ou até o firebird executa este segundo select da clausula where para cada registro do primeiro select -> não acredito que o firebird faça isso, mas porque a tamanha lentidão?.
Sempre que eu coloquei selects dentro da clausula where tive problemas com lentidão.
GOSTEI 0
Emerson Nascimento
12/01/2005
para funcionar bem, você precisa de um índice para o campo [u:e41d8e688b]vcont[/u:e41d8e688b] (creio que já exista, pois você afirmou que esse campo é a chave primária) e um outro índice para os campos [i:e41d8e688b]data[/i:e41d8e688b] e [i:e41d8e688b]codcli[/i:e41d8e688b]. você os tem?
GOSTEI 0
Larry
12/01/2005
para funcionar bem, você precisa de um índice para o campo [u:dfe1acc32e]vcont[/u:dfe1acc32e] (creio que já exista, pois você afirmou que esse campo é a chave primária) e um outro índice para os campos [i:dfe1acc32e]data[/i:dfe1acc32e] e [i:dfe1acc32e]codcli[/i:dfe1acc32e]. você os tem?
Oi,
Os tres campos ja tem indice.
GOSTEI 0
Emerson Nascimento
12/01/2005
o group by precisa de um índice pelos dois campos. deveria ser algo assim
Indice1 - cont
Indice2 - data, codcli
Indice1 - cont
Indice2 - data, codcli
GOSTEI 0
Larry
12/01/2005
o group by precisa de um índice pelos dois campos. deveria ser algo assim
Indice1 - cont
Indice2 - data, codcli
Oi,
Peguei o problema:
O campo data é do tipo timestamp (data+hora), então criei um campo Data1 com ´computed by cast(data as date)´ e assim tava lento.
Agora criei um campo Data2 do tipo date, transferi as informações do campo Data1 e criei os indices. Ai sim ficou muito mais rapido.
Valeu.
GOSTEI 0