Clipper On Line • Ver Tópico - Select dentro de outro Select
Página 1 de 1

Select dentro de outro Select

MensagemEnviado: 06 Mai 2017 20:55
por janio
Pessoal,

A consulta abaixo me retornam TODOS os produtos comprados de um determinado fornecedor:

SELECT a.codigo, a.descri
FROM a03prd a
INNER JOIN a04dnf b ON ( a.codigo=b.codprd )
WHERE b.CodFrn=50
GROUP BY a.codigo
ORDER BY a.descri


Retorna algo como:

20701 ABS LIVRE ATIVA CLASSIC CA 8 UN
6987 ACHOC ITALAC 200ML
15145 ACHOC ITALAC SC 400G
16462 ACHOC PO MAGICO 200G
...


Com este resultado, agora preciso pegar a ULTIMA COMPRA DE CADA PRODUTO! Como faço?

Janio

PS: tabela de compras a04dnf, campo data datent

Select dentro de outro Select

MensagemEnviado: 07 Mai 2017 00:46
por JoséQuintas

Select dentro de outro Select

MensagemEnviado: 07 Mai 2017 09:56
por janio
Quase dando certo...

Com MAX() ele me retorna a ultima data... blz.

Mas os outros dados do SELECT (qtdprd, vlruni, numnot) não são referentes a ultima data. Estranho viu

select b.codigo, b.descri, a.qtdprd, a.vlruni, a.numnot, Max(a.datent)
from a04dnf a
inner join a03prd b on (a.codprd=b.CODIGO)
where a.codfrn=3
group by a.codprd
order by b.descri

Select dentro de outro Select

MensagemEnviado: 07 Mai 2017 11:38
por JoséQuintas
Normal: o Max() faz retornar a última data, apenas para o campo da data.
Essa vai ser a referência para o outro select.
Lembrando que pode ter mais de uma compra nessa data.
Se for a última, e tiver sequencial de lançamento, talvez seja mais interessante o último lançamento, ou talvez somar os lançamentos dessa última data.

Lembrando que nessa parte ainda sou principiante.
Ainda estou na migração parcial, e por isso esses selects ainda não fazem parte do meu dia-a-dia.
Quem está acostumado provavelmente poderá ter uma solução melhor.

Select dentro de outro Select

MensagemEnviado: 08 Mai 2017 09:25
por janio
AlxSts, please!

:-o

Tentei tudo ja :(Neg

Select dentro de outro Select

MensagemEnviado: 09 Mai 2017 00:06
por janio
Os dados vieram corretos no codigo abaixo, porem, nao sei se eh a forma mais recomendavel... ate pq achei um pouco lento.

select a.codprd, a.qtdprd, a.vlruni, a.datent
from a04dnf a
inner join (select max(datent) as data from a04dnf b group by b.codprd) c on c.data = a.datent
where a.codfrn=3
group by a.codprd
order by a.codprd

Select dentro de outro Select

MensagemEnviado: 09 Mai 2017 20:23
por janio
Para conseguir o resultado que eu queria, tive que usar a boa e velha GAMBIARRA!

Ficou muito bom. Rapido. Uma bala

- Listo todos os produtos comprados do fornecedor no periodo
- Organizo com data DECRESCENTE
- Descarto os outros resultado de compras q nao seja a ultima, pegando apenas o primeiro resultado de cada produto

         cQuery = "SELECT a.codprd, a.uniprd, a.unicom, a.qtdprd, a.vlruni, a.numnot, a.datent, b.descri, b.sldstk " + ;
                  "FROM a04dnf a " + ;
                  "INNER JOIN a03prd b ON ( a.codprd=b.codigo ) " + ;
                  "WHERE a.is_deleted = 'N' and a.CodFrn='&nCodFrn' and a.datent between '&vDataI_' and '&vDataF_' " + ;
                  "ORDER BY b.descri, a.datent DESC "

         GERA_TAB()
         use &dbftmp as cQuery NEW SCROLLABLE
         DbGoTop()
      
         Do While !Eof()
         
            nCodPrd := CodPrd
            nConta  := 0
            
            Do While nCodPrd = CodPrd
                           
               If nConta = 0                           
                  @ PROW() + 01,000 SAY StrZero(CodPrd,5) + " " + Left(DesCri,40)
                  @ PROW()     ,048 SAY UniCom
                  @ PROW()     ,051 SAY UniPrd   
                  @ PROW()     ,056 SAY DatEnt
                  @ PROW()     ,069 SAY QtdPrd Pict "@E 99,999.99"
                  @ PROW()     ,083 SAY VlrUni Pict "@E 99,999.99"
                  @ PROW()     ,096 SAY NumNot               
                  @ PROW()     ,123 SAY SldStk Pict "@E 99,999.99"
                  @ PROW() + 01,000 SAY REPLICATE("-",132)
               Endif
               
               nConta++
   
               DbSkip()
               
            Enddo
            
         Enddo

         Use

Select dentro de outro Select

MensagemEnviado: 11 Set 2017 19:05
por janio
Pessoal,

Estou precisando fazer uma nova consulta que, imagino, também se aplique "select dentro de outro select"!

O negocio é meio complicadim hehehe

Basicamente:
Seleciono os produtos que ENTRARAM num período (isso é facil). Com o resultado dessa Query em maos, agora preciso selecionar quais desses registros (produtos) NÃO TIVERAM vendas no mesmo período.

Select distinct a.codigo, a.descri, max(b.DATENT)
from a03prd a
inner join a04dnf b on (a.codigo=b.codprd)
where b.DATEMI between '2016-01-01' and '2016-01-31'
group by a.codigo
order by a.codigo


Resulta:
002 ARROZ PARB PAI JOAO 1K 2016-01-13
003 ARROZ PARB PAI JOAO 1K 2016-01-28
016 ARROZ BRANCO GRANEL 1K 2016-01-13
034 MAC NISSIN T MONICA GALINHA 90G 2016-01-19
102 TRIGO D BENTA CF 1K 2016-03-01


Quais desses produtos NAO TIVERAM VENDAS no mesmo período? Eis a questão

Select dentro de outro Select

MensagemEnviado: 11 Set 2017 19:24
por janio
Pessoal,

Seria mais ou menos a Query abaixo!
Select * 
from a04dnf e
where e.datent between '2016-01-01' and '2016-01-31' and
   not exists
   (
   Select null
   from a03dpd d
   where d.codprd = e.codprd
   )


Todos os produtos que tiveram ENTRADA no período tal, mas que não tem vendas!

A única coisa q ta faltando na query eh informar no select da tabelas de vendas o período que não tenha havido venda. Não é nunca vendeu!. É não vendeu no período que for informado

Select dentro de outro Select

MensagemEnviado: 11 Set 2017 20:11
por janio
Acho q cheguei a um resultado, porem, algo muito interessante esta acontecendo:

Da maneira abaixo a consulta eh instantanea (sem limitação de período na tabela vendas - segundo select).
Select distinct e.codprd, b.descri, max(e.datent)
from a04dnf as e
inner join a03prd as b on (b.codigo=e.codprd)
Where e.datent between '2016-01-01' and '2016-01-31' and
   not exists
   (
   Select null
   from a03dpd as t
   where t.codprd = e.codprd
   )
group by e.datent


Se limito o periodo na tabela vendas (segundo select), a consulta demora uma eternidade:
Select distinct e.codprd, b.descri, max(e.datent)
from a04dnf as e
inner join a03prd as b on (b.codigo=e.codprd)
Where e.datent between '2016-01-01' and '2016-01-31' and
   not exists
   (
   Select null
   from a03dpd as t
   where t.codprd = e.codprd and t.datemi between '2016-01-01' and '2016-01-31'
   )
group by e.datent

Imaginava que seria exatamente o contrário: Com limitação de data... rapido! Sem limitação de data... lento (já que teoricamente teria que varrer a tabela inteira)

Select dentro de outro Select

MensagemEnviado: 11 Set 2017 21:11
por JoséQuintas
Chute que veio na cabeça...

SELECT item, MAX( datamaxima ) AS data, SUM( qtvenda ) AS total FROM
(
( SELECT item, MAX( dtcompra ) AS datamaxima, 0 AS qtvenda FROM compras GROUP BY item ) AS tempcompras
UNION ALL
( SELECT item, NULL AS datamaxima, COUNT(*) AS qtvenda FROM vendas GROUP BY item ) AS tempvendas
) AS tempcompravenda
GROUP BY item HAVING total = 0

uma seleção de compras
uma seleção de vendas
junta tudo
faz o filtro

De repente pode ser mais rápido, porque vai fazer selects únicos, e não um select pra cada item do select anterior.

Mas como falei, é chute, ainda não faz parte do meu dia a dia fazer essas coisas, então não sei se aceita ou qual o comportamento real.

Select dentro de outro Select

MensagemEnviado: 11 Set 2017 23:34
por janio
Quintas, não funcionou!

Mas encontrei uma maneira mais simples que trouxe o resultado desejado e de forma instantanea! Saí de 46 segundos da forma anterior, para instantaneo.

Select t.codprd, b. descri
from (Select distinct codprd, datent from a04dnf) as t
left join (select distinct codprd from a03dpd where (datemi between '2016-01-01' and '2016-01-31') c on t.codprd=c.codprd
inner join a03prd as b on (b.codigo=t.codprd)
where (t.datent between '2016-01-01' and '2016-01-31') and (c.codprd is null)
order by b.descri


Todos produtos que tiveram COMPRA no período informado, mas não tiveram VENDA no mesmo período

1. Filtro dos produtos que tiveram compra no período (where (t.datent between '2016-01-01' and '2016-01-31') )
2. Filtro dos produtos que tiveram venda no período (left join)
3. Filtro dos produtos que tiveram compra, mas nao tiveram venda (left join), ou seja, constam na tabela t (a esquerda) e não constam na tabela c (a direita)

Select dentro de outro Select

MensagemEnviado: 12 Set 2017 09:10
por JoséQuintas
legal, pelo menos serviu pra ajudar.
Reduziu o que podiam ser milhares de SELECTs (um por produto), para dois SELECTs.

Select dentro de outro Select

MensagemEnviado: 10 Jan 2018 10:28
por alaminojunior
Só refrescando a memória, pois sei que as vezes alguns detalhes passam sem a gente lembrar:

Algumas vezes (ou quase sempre) a demora numa consulta pode ser falta de indexar as colunas que se usam na sentença como parâmetro de busca.