Fórum SQL complicada. Usando Data #48864

12/01/2005

0

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]


Larry

Larry

Responder

Posts

12/01/2005

Emerson Nascimento

select data, codcli, max(valor) as UltimaVenda
from vendas
where data<date-30
group by data, codcli


Responder

Gostei + 0

12/01/2005

Larry

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?


Responder

Gostei + 0

13/01/2005

Thomaz_prg

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.


Responder

Gostei + 0

13/01/2005

Larry

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?


Responder

Gostei + 0

13/01/2005

Afarias

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+


Responder

Gostei + 0

13/01/2005

Fsflorencio

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


Responder

Gostei + 0

14/01/2005

Larry

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?


Responder

Gostei + 0

14/01/2005

Larry

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 ???


Responder

Gostei + 0

14/01/2005

Larry

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.


Responder

Gostei + 0

14/01/2005

Emerson Nascimento

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)


Responder

Gostei + 0

14/01/2005

Adilsond

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:

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



Responder

Gostei + 0

15/01/2005

Emerson Nascimento

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.


Responder

Gostei + 0

17/01/2005

Larry

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.


Responder

Gostei + 0

17/01/2005

Emerson Nascimento

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?


Responder

Gostei + 0

17/01/2005

Larry

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.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar