Clipper On Line • Ver Tópico - Montar SELECT

Montar SELECT

Discussão sobre SQL

Moderador: Moderadores

 

Montar SELECT

Mensagempor gilbertosilverio » 27 Set 2020 11:55

Ola Amigos,

Baseado em exemplos do forum, montei esta rotina para testar SQL, mais nao consegui pegar os valores de uma terceira tabela.

FUNCTION PORTAL_array_muda()  // modelo de filtro de array
     LOCAL oQUERY
     PRIVATE nCurrent, cDescricao, oELEMENTO, aVetorPai := {}, aVetorFilho := {}, oBrw1, oBrw2, oDlg_Busca
     PRIVATE aTITULO:={}, zRec, xLOJA:=[01], zRec_02, aTIT_02:={}

     PRIVATE cTXT:=DATE(), cTXT1:=DATE()+10, xQTDE:=0, DTFIM, DTINI, cARQ:=0
     PRIVATE oDlg, aResult:= {}, oServer, TITULO:={}, xQTDEPENDENTE:=0, xVALOR:=0, xFRETE:=0

     A_MsgGetFecha( [Cotações diaria], [Entre periodo a pesquisar ], @cTXT, @cTXT1 )

     oServer := MySqlConnection( "127.0.0.1", "", "root", "123*123*" )

     DTINI:= Transform( Dtos( cTXT  ), "@R 9999-99-99" ) //'2020-05-06'
     DTFIM:= Transform( Dtos( cTXT1 ), "@R 9999-99-99" ) //'2020-05-06'

     oServer:Open()
     oServer:Execute( "USE PORTAIS" )

     oQuery := oServer:Execute( [SELECT * FROM entraportal WHERE dt_fecha BETWEEN ']+DTINI+[' AND ']+DTFIM+['] )

     DO WHILE ! oQuery:Eof()
        aAdd( aVetorPai, { oQuery:Fields("status"          ):Value      ,;  //   1
                           oQuery:Fields("portal"          ):Value      ,;  //   2
                           oQuery:Fields("idarquivo"       ):Value      ,;  //   3
                           oQuery:Fields("dt_fecha"        ):Value      ,;  //   4
                           oQuery:Fields("hr_fecha"        ):Value      ,;  //   5
                           oQuery:Fields("identraportal"   ):Value      ,;  //   6
                           oQuery:Fields("CodVend"         ):Value      ,;  //   7
                           oQuery:Fields("uf"              ):Value      ,;  //   8
                           oQuery:Fields("cliente"         ):Value      ,;  //   9
                           oQuery:Fields("cnpj"            ):Value      ,;  //   10
                           oQuery:Fields("filial"          ):Value      })  //   11
        oQuery:MoveNext()
     ENDDO
     oQuery:Close()

     IF LEN(aVETORPAI) > 0
        INIT DIALOG oDlg_Busca TITLE "Pesquisar Produto - Filial: " +str(vLoja,4) AT 0,0 SIZE 1180,640 ;
             FONT HFont():Add( 'tahoma',0,-13,400,,,) CLIPPER                         ;
             STYLE WS_POPUP+WS_CAPTION+WS_SYSMENU+WS_MAXIMIZEBOX+WS_SIZEBOX+DS_CENTER

             @ 13,070 BROWSE oBrw1 ARRAY SIZE 1160,310 STYLE WS_TABSTOP         ;
                      ON POSCHANGE {|| cID := oBrw1:aarray[oBRW1:nCurrent, 06], ;
                                       PORTAL_ARRAY_MUDA_onPosChange(@cID),     ;
                                       oBrw2:Refresh(), oDlg_Busca:Refresh() }

             oBrw1:nHeadHeight := 25
             oBrw1:aArray      := aVetorPai
             oBrw1:nColumns    := 14
             oBrw1:freeze      := 1
             oBrw1:lDispHead   := .T.
             oBrw1:lSep3d      := .T.
             oBrw1:lAdjRight   := .T.

             Hwg_CreateArList( oBrw1, aVETORPAI )

             aTITULO:= { [Status], [Portal], [Nº Cotacao], [Fechamento], [Horario], [Id], [CodVe], [UF], [Cliente], [CNPJ], [Filial] }

             FOR nI := 1 TO Len(oBrw1:aColumns)
                 oBrw1:aColumns[nI]:heading   := aTITULO[nI]
                 IF (oBrw1:aColumns[nI]):Type == "C"
                    oBrw1:aColumns[nI]:nJusHead  := DT_LEFT
                 ELSE
                    oBrw1:aColumns[nI]:nJusHead  := DT_LEFT
                 ENDIF
                 IF (oBrw1:aColumns[nI]):Type == "C"
                    oBrw1:aColumns[nI]:nJusLin   := DT_LEFT
                    oBrw1:aColumns[nI]:Picture   := [@!]
                 ELSEIF (oBrw1:aColumns[nI]):Type == "N"
                    oBrw1:aColumns[nI]:nJusLin   := DT_RIGHT
                 ENDIF
             NEXT

             FOR nG := 1 TO Len(oBrw1:aColumns)
                 IF (oBrw1:aColumns[nG]):Type == "N"
                    zREC:=oBrw1:aarray[oBrw1:nCurrent, nG]
                    IF VAL(SUBSTR(STR(zREC,12,2),11,2)) > 0
                       oBrw1:aColumns[nG]:Picture := [@E 999,999,999.99]
                    ELSE
                       oBrw1:aColumns[nG]:Picture := [@E 999,999,999]
                    ENDIF
                 ENDIF
             NEXT

             oBrw1:aColumns[2]:bColorBlock := ;
                {|n| IF( (aVETORPAI[oBrw1:nCurrent][2]=[SINTESE] .OR. aVETORPAI[oBrw1:nCurrent][2]=[GTPLAN] ), {x_RED,   x_WHITE,  x_WHITE, x_GRAY}, ;
                     (IF( aVETORPAI[oBrw1:nCurrent][2]=[APOIO],   {x_GREEN,    x_WHITE,  x_WHITE, x_GRAY},  ;
                     IF(  aVETORPAI[oBrw1:nCurrent][2]=[BIONEXO], {x_DARKBLUE, x_WHITE,  x_WHITE, x_GRAY},  ;
                                                                  {x_BLUE,     x_WHITE,  x_WHITE, x_GRAY} ))))}

             oBrw1:aColumns[01]:Length  := 15
             oBrw1:aColumns[02]:Length  := 15

             oBrw1:aColumns[02]:bHeadClick := {|| p_fobrowse2_1_onHeadClick( ) }
             oBrw1:aColumns[04]:bHeadClick := {|| p_fobrowse2_2_onHeadClick( ) }
             oBrw1:aColumns[03]:bHeadClick := {|| p_fobrowse2_3_onHeadClick( ) }

             @ 13,390 BROWSE oBrw2 ARRAY SIZE 960,200 STYLE WS_TABSTOP AUTOEDIT

             oBrw2:nHeadHeight := 24
             oBrw2:nColumns    := 5
             oBrw2:freeze      := 1

             nCurrent   := oBrw1:nCurrent

             cARQ := aVETORPAI[nCurrent,6] //iPosicao é a coluna onde está a descrição

             aGridFilho := {}

             FOR EACH oElemento IN aVetorFilho
                IF oElemento[6] = cARQ
                   aAdd( aGridFilho, { oElemento[1], oElemento[2], oElemento[3], oElemento[4], oElemento[5], oElemento[6], oElemento[7], oElemento[8],oElemento[9],oElemento[10] } )
                ENDIF
             NEXT

             oBrw2:aArray := aGridFilho

             IF LEN(aGridFilho) > 0
                aTIT_02 := { [Codigo], [Descricao], [CodProd], [Seque], [Validade], [id], [Marca],[CNPJ] ,[PRECO],[CUSTO]}
                Hwg_CreateArList( oBrw2, aGridFilho )
                FOR nI := 1 TO Len(oBrw2:aColumns)
                    oBrw2:aColumns[nI]:heading   := aTIT_02[nI]
                    IF (oBrw2:aColumns[nI]):Type == "C"
                       oBrw2:aColumns[nI]:nJusHead  := DT_LEFT
                    ELSE
                       oBrw2:aColumns[nI]:nJusHead  := DT_LEFT
                    ENDIF
                    IF (oBrw2:aColumns[nI]):Type == "C"
                       oBrw2:aColumns[nI]:nJusLin   := DT_LEFT
                       oBrw2:aColumns[nI]:Picture   := [@!]
                    ELSEIF (oBrw2:aColumns[nI]):Type == "N"
                       oBrw2:aColumns[nI]:nJusLin   := DT_RIGHT
                    ENDIF
                NEXT

                FOR nG := 1 TO Len(oBrw2:aColumns)
                    IF (oBrw2:aColumns[nG]):Type == "N"
                       zREC_02:=oBrw2:aarray[oBrw2:nCurrent, nG]
                       IF VAL(SUBSTR(STR(zREC_02,12,2),11,2)) > 0
                          oBrw2:aColumns[nG]:Picture := [@E 999,999,999.99]
                       ELSE
                          oBrw2:aColumns[nG]:Picture := [@E 999,999,999]
                       ENDIF
                    ENDIF
                NEXT

             ENDIF
             oBrw2:Refresh()

             @  980,600 BUTTONEX oButtonex1 CAPTION "&Abrir"   SIZE 98,32 STYLE WS_TABSTOP ;
                        ON CLICK {|| .T. }
                        oButtonex1:Anchor := 12

             @ 1080,600 BUTTONEX oButtonex2 CAPTION "Sai&r"   SIZE 98,32 STYLE WS_TABSTOP ;
                        ON CLICK {|| DBCLOSEALL(), oDlg_Busca:CLOSE() }
                        oButtonex2:Anchor := 12

        ACTIVATE DIALOG oDlg_Busca
     ELSE
        HWG_MSGINFO([Não existem dados para o periodo])
     ENDIF
RETURN NIL

FUNCTION PORTAL_ARRAY_MUDA_ONPOSCHANGE(cARQ)
   LOCAL oQUERY

       aGridFilho := {} ; aVetorFilho:={}

       oQuery := oServer:Execute( [SELECT * FROM WGG WHERE id_entraportal = ] + ALLTRIM(STR(cARQ,9)) )

       DO WHILE ! oQuery:Eof()
           aAdd( aVetorFilho, { oQuery:Fields("DESCRICAO"       ):Value      ,;  //   1
                                oQuery:Fields("CODPROD"         ):Value      ,;  //   2
                                oQuery:Fields("SEQUE"           ):Value      ,;  //   3
                                oQuery:Fields("QTDE"            ):Value      ,;  //   4
                                oQuery:Fields("UNIDA"           ):Value      ,;  //   5
                                oQuery:Fields("ID_ENTRAPORTAL"  ):Value      ,;  //   6   * CHAVE DE PESQUISA
                                oQuery:Fields("MARCA"           ):Value      ,;  //   7
                                oQuery:Fields("PRECO"           ):Value      ,;  //   8
                                oQuery:Fields("CUSTO"           ):Value      ,;  //   9
                                oQuery:Fields("CNPJHOSP"        ):Value      })  //   10
          oQuery:MoveNext()
       ENDDO
       oQuery:Close()

       FOR EACH oElemento IN aVetorFilho
          IF oElemento[6] = cARQ
             aAdd( aGridFilho, { oElemento[1], oElemento[2], oElemento[3], oElemento[4], oElemento[5], oElemento[6], oElemento[7], oElemento[8], oElemento[9], oElemento[10] } )
          ENDIF
       NEXT

       oBrw2:aArray := aGridFilho
       IF LEN(aGridFilho) > 0
          aTIT_02 := { [Descricao], [CodProd], [Seque], [Qtde], [Unidade], [id],[Marca],[Preco],[Custo],[CNPJ] }
          Hwg_CreateArList( oBrw2, aGridFilho )
          FOR nI := 1 TO Len(oBrw2:aColumns)
              oBrw2:aColumns[nI]:heading   := aTIT_02[nI]
              IF (oBrw2:aColumns[nI]):Type == "C"
                 oBrw2:aColumns[nI]:nJusHead  := DT_LEFT
              ELSE
                 oBrw2:aColumns[nI]:nJusHead  := DT_LEFT
              ENDIF

              IF (oBrw2:aColumns[nI]):Type == "C"
                 oBrw2:aColumns[nI]:nJusLin   := DT_LEFT
                 oBrw2:aColumns[nI]:Picture   := [@!]
              ELSEIF (oBrw2:aColumns[nI]):Type == "N"
                 oBrw2:aColumns[nI]:nJusLin   := DT_RIGHT
              ENDIF
          NEXT
          FOR nG := 1 TO Len(oBrw2:aColumns)
              IF (oBrw2:aColumns[nG]):Type == "N"
                 zREC_02:=oBrw2:aarray[oBrw2:nCurrent, nG]
                 IF VAL(SUBSTR(STR(zREC_02,12,2),11,2)) > 0
                    oBrw2:aColumns[nG]:Picture := [@E 999,999,999.99]
                 ELSE
                    oBrw2:aColumns[nG]:Picture := [@E 999,999,999]
                 ENDIF
              ENDIF
          NEXT
       ENDIF
       oBrw2:Refresh()
return nil


O que estou tentando fazer e pegar o PRECO da tabela BIODEPAES, quando houver e incluir no browse, so que o SELECT me retorna um unico item, que no caso e o unico que consta na tabela BIODEPAES.

Ja tentei de todas as maneira no Heid, mais nao consigo obter este retorno.

Observem que no pedido constam 4 itens, mais so consigo pegar 1, que e o que consta na tabela BIODEPAES.

Por favor, alguém poderia me ensinar como e que devo montar este select, para que eu consiga mesclar estas duas tabelas.

Grato.
Anexos
T1.png
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

Montar SELECT

Mensagempor alxsts » 27 Set 2020 14:52

Olá!

O problema é que você está usando INNER JOIN. Com este tipo de junção, são retornados apenas os registros que exitem nas duas tabelas. Troque para LEFT JOIN. Para entender melhor isto, estude o artigo MySQL Join. Pesquise o assunto na internet. Existem muitos materiais sobre o tema.
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Montar SELECT

Mensagempor JoséQuintas » 27 Set 2020 16:01

Exato.
Por isso preferi o LEFT, por poder existir coisa "estranha".

Se pedir o financeiro com LEFT JOIN de clientes, vém todo financeiro mesmo se o cliente não tiver cadastro.
Se pedir com INNER JOIN, só vém financeiro se tiver cliente cadastrado.

Os outros, provavelmente são um oposto:
Provavelmente OUTER JOIN vai trazer somente o que não tem cliente cadastrado
E provavelmente RIGHT JOIN vai trazer todos os clientes, mesmo sem financeiro

No caso do seu comando, ao usar INNER JOIN, automaticamente excluiu do retorno o que não tinha valor cadastrado.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Montar SELECT

Mensagempor JoséQuintas » 27 Set 2020 16:22

Olhei depois o link, e vi que também tem o CROSS JOIN.

Provavelmente é tudo de tudo, todos os clientes, com todo o financeiro, não importa se cliente tem financeiro, ou se financeiro tem cliente.

Nota:
O Alexsts já tinha respondido, e já tinha mostrado o link.
Apenas achei que explicando do jeito que fiz pode ser mais fácil de memorizar.
Por exemplo, no link diz que o CROSS JOIN é um produto cartesiano. Acho mais fácil entender se disser igual acima.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Montar SELECT

Mensagempor gilbertosilverio » 27 Set 2020 18:50

Ola,

Agradeço a todos.

Isso e muito complicado... kkkk, ja li muito e cada vez entendo menos.

Ja tinha testado com o LEFT também, mais o retorno e sempre estranho, em linha de pedidos em que não ha nenhum item cadastrado na tabela de preços, as vezes retorna todos os campos preenchidos.

O que não entendo é, fiz uma clausula dizendo que quero os itens onde os códigos da duas tabelas são iguais , pela logica não teria que retornar somente os itens iguais nas duas tabelas, e o que não fosse retorna em branco.

Com o Left ate funciona, mais os itens que não constam nas duas tabelas, as vezes retorna com dados que não tem nada haver...

Sei que o erro e meu, mais e bem complicado...

Vou continuar testando, e achar o meu erro.

ps: Simões, desculpe por postar aqui, e que esta lendo os post da Hwgui e nem percebi que esta no lugar errado.
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

Montar SELECT

Mensagempor JoséQuintas » 27 Set 2020 21:41

o seu
select wgg.codprod, wgg.descricao, wgg.preco, biodepaes.preco, biodepaes.custo
from wgg
inner join biodepaes
where id_entraportal = '121' and wgg.codprod = biodepais.codprobi


acostume a dizer como está relacionando, acho que é melhor

left join biodepaes on wgg.codprod = biodepaes.codprobi


relacionou o código de produto, e vai trazer zerado/null o que não existir em biodepaes, porque usou LEFT

se tiver coisa repetida no biodepaes, código de produto repetido, vai trazer multiplicados os registros, tem essa também.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Montar SELECT

Mensagempor JoséQuintas » 27 Set 2020 21:51

Pera aí.... será que não está confundindo?

Não vai vir zerado, vai vir com NULO. Isso não é zero.
Talvez tenha que complicar pra vir zerado.
Além disso, tem campo com nome repetido, vai precisar renomear.

select wgg.codprod, wgg.descricao, wgg.preco, 
if( biodepaes.preco = nul, 0, biodepaes.preco ) as biopreco,
if( biodepaes.custo = nul, 0, biodepaes.custo ) as biocusto
from wgg
left join biodepaes on wgg.codprod = biodepais.codprobi
where id_entraportal = '121'
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Montar SELECT

Mensagempor alxsts » 28 Set 2020 01:05

Olá!

JoséQuintas escreveu:Talvez tenha que complicar pra vir zerado.

COALESCE() Function
Return the first non-null value in a list

SELECT w.codprod,
       w.descricao,
       w.preco,
       coalesce(b.preco,0)  as biopreco,
       coalesce(b.custo,0)  as biocusto
FROM wgg w
   LEFT JOIN biodepaes b ON w.codprod = b.codprobi
WHERE id_entraportal = '121'  /* De onde vem esta coluna? */
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Montar SELECT

Mensagempor gilbertosilverio » 28 Set 2020 06:57

Olá,

Quintas, da sua maneira funciona, mais retorna null os valores que não existem, já com a função coalesce() do Alexandre, retorna correto.

Alexandre o '121', vem do 1º browse, referente ao relacionamento de PEDIDO + ITENS, conforme navego nos pedidos, os itens são alterados, so que para complicar tem uma terceira tabela, com itens já "ganhos", que e de onde preciso tirar estes preços...

Creio que e ai que estou enroscando, com DBF e fácil, abro os arquivos e vou pesquisando, aqui com SQL, enrosco... kkkkk

São muitos detalhes, mais chego lá.

Grato.
Anexos
t1.png
t2.png
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

Montar SELECT

Mensagempor gilbertosilverio » 28 Set 2020 08:30

Ola,

Alexandre, Quintas,

Funcionou perfeitamente, o único detalhe e um pequeno delay quando há muitos itens no pedido, minha preocupação e com 50 usuários navegando em um browse com essa rotina, não sei como o server vai se comportar... Com dbf nem pisca... kkkkk

Existe a possibilidade de trabalhar como o campo indexado como no dbf para aumentar a performance de pesquisas no SQL.

Como ficou:
FUNCTION PORTAL_ARRAY_MUDA_ONPOSCHANGE(cARQ)
   LOCAL oQUERY, oQuery1

       aGridFilho := {} ; aVetorFilho:={}

       oQuery1 := [SELECT w.descricao, ]
       oQuery1 += [       w.codprod, ]
       oQuery1 += [       w.seque, ]
       oQuery1 += [       w.qtde, ]
       oQuery1 += [       w.unida, ]
       oQuery1 += [       w.id_entraportal, ]
       oQuery1 += [       w.marca, ]
       oQuery1 += [       w.cnpjhosp, ]
       oQuery1 += [coalesce(b.preco,0)  as biopreco, ]
       oQuery1 += [coalesce(b.custo,0)  as biocusto, ]
       oQuery1 += [       b.cnpjhosp, ]
       oQuery1 += [       b.codprobi ]
       oQuery1 += [FROM wgg w ]
       oQuery1 += [LEFT JOIN biodepaes b ]
       oQuery1 += [ON w.codprod = b.codprobi AND w.cnpjhosp = b.cnpjhosp ]
       oQuery1 += [WHERE w.id_entraportal = ']+ ALLTRIM(STR(cARQ,9)) + [']

       oQuery := oServer:Execute( oQuery1 )

       DO WHILE ! oQuery:Eof()
           aAdd( aVetorFilho, { oQuery:Fields("DESCRICAO"       ):Value      ,;  //   1
                                oQuery:Fields("CODPROD"         ):Value      ,;  //   2
                                oQuery:Fields("SEQUE"           ):Value      ,;  //   3
                                oQuery:Fields("QTDE"            ):Value      ,;  //   4
                                oQuery:Fields("UNIDA"           ):Value      ,;  //   5
                                oQuery:Fields("ID_ENTRAPORTAL"  ):Value      ,;  //   6   * CHAVE DE PESQUISA
                                oQuery:Fields("MARCA"           ):Value      ,;  //   7
                                oQuery:Fields("bioPRECO"        ):Value      ,;  //   8
                                oQuery:Fields("bioCUSTO"        ):Value      ,;  //   9
                                oQuery:Fields("CNPJHOSP"        ):Value      })  //   10
          oQuery:MoveNext()
       ENDDO
       oQuery:Close()


Novamente agradeço pela a ajuda de todos.
Anexos
t1.png
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

Montar SELECT

Mensagempor JoséQuintas » 28 Set 2020 10:58

gilbertosilverio escreveu:Funcionou perfeitamente, o único detalhe e um pequeno delay quando há muitos itens no pedido, minha preocupação e com 50 usuários navegando em um browse com essa rotina, não sei como o server vai se comportar... Com dbf nem pisca... kkkkk
Existe a possibilidade de trabalhar como o campo indexado como no dbf para aumentar a performance de pesquisas no SQL.


Tem mais de meio milhão de produtos no pedido? kkkk

Seguinte:

No SQL é igual DBF, se tiver índice fica muito mais rápido.

MAS.... só precisa existir o índice, NÃO precisa fazer mais nada no SELECT.

Vai lá no SQL:
Vai lá nos pedidos cria índice por pedido
Vai lá nos produtos, cria índice por produto
Vai lá nos produtos de pedido, cria índice por "pedido, produto"
E por aí vai.

O SQL usa automaticamente o índice que ele considerar o melhor pra obter o resultado.
NÃO precisa mexer no programa, precisa só criar os índices no servidor.

IMPORTANTE:
Crie índice pensando em pesquisas e não pensando em resultado.
Se vai tirar um relatório de clientes em ordem alfabética.... isso NÃO precisa índice por nome.
Se vai pesquisar nomes... aí sim um índice por nome se torna interessante.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Montar SELECT

Mensagempor JoséQuintas » 28 Set 2020 11:09

Putz......
Então é a partir de agora que vai gostar muito mais de SQL.
Se já está estava achando interessante, e nem usava índice...

Saiba que estava usando o modo carroça.
Criando índice, vai virar o modo avião.

A partir de agora, pode achar até que não funcionou, de tão rápido que vai ficar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Montar SELECT

Mensagempor gilbertosilverio » 28 Set 2020 11:51

Quintas,

Tenho certeza que e devido eu ai não ter dominado o uso do SQL, como disse, quanto mais leio, mais confuso fico...

Pra quem ta acostumado com DBF, estranha com certeza.

Meio milhão não, mais tem umas cotações de ate 400 itens, junto com a base de pesquisa da tabela de preço de 110.000, achei um pouco lenta a resposta, ainda mais pra quem vai rolando as linhas no browse.

Em teste, a pesquisa de 100 itens demora em torno de 1,65 segundos, o problema e esse, vc vai descendo no browse, trava, ai de repente dispara, tenho certeza que a Veiarada vai reclamar, pq antes não travava... kkkkkk

Vamos em frente, to gostando da brincadeira...
Anexos
t1.png
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

Montar SELECT

Mensagempor JoséQuintas » 28 Set 2020 12:27

Você está usando pelo Harbour, com lib do Harbour, aí não sei dizer exatamente o comportamento.
O que percebi num teste do SQLMIX é que o Harbour faz uma espécie de cache, vai trazendo uma quantidade conforme vai precisando.

Considere como ponto de partida que trazer 100.000 registros demora menos de 1 segundo, e vém tudo de uma vez.
No máximo, seria uma pausa de 1 segundo pro cache do Harbour, ao navegar, se por exemplo trouxer 10.000 por vez.
Isso rede local, por internet depende da internet.

No SQL, o que demora é fazer muitas pesquisas, e não trazer muita coisa de uma vez.
Quando digo muitas pesquisas: tipo, tem lá na tela vários códigos, e fica pesquisando um de cada vez, quando poderia trazer tudo da tela de uma vez.
Digamos que a pesquisa demore meio segundo: se pesquisar 10 códigos de uma vez demora 0.5 segundo, se pesquisar um de cada vez vai demorar 5 segundos, meio pra cada pesquisa. Não é exatamente essa proporção, é só pra dar uma idéia de como tirar vantagem.

A partir daí, é você que precisa fazer o ajuste conforme seu programa/suas pesquisas.

Veja também se pode aproveitar o resultado do SELECT no browse, isso de ficar convertendo deixa extremamente lento.

Até por isso eu preferi usar o browse diretamente do ADO - no meu caso.
Demora muito mais a conversão do que o SELECT, então usar diretamente o resultado se torna instantâneo, que no meu caso o resultado é no formato ADO.

Se no seu caso o formato é array, tente usar diretamente o array que já vém pronto, e não criar outro array só para o browse.

Aliás.... o HEIDISQL é uma boa base de testes.
A velocidade que obter no HEIDISQL é a que mesma que teria que acontecer no programa.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Montar SELECT

Mensagempor Poka » 28 Set 2020 12:59

Boa tarde

Gilberto escreveu
o problema e esse, vc vai descendo no browse, trava, ai de repente dispara, tenho certeza que a Veiarada vai reclamar, pq antes não travava... kkkkkk


Gilberto pra resolver poderia fazer pra mostrar paginado pegando e mostrando só o que cabe na tela.
vou montar um executável aqui pra vc testar.

Uso firebird , Harbour e hmg extend
usando no select FIRST E SKIP dá pra fazer.
acredito que dá pra passar no mysql.
infelizmente não posso fazer no momento, mas até o final da semana dou um jeito de enviar.

Um abraço

Poka
Avatar de usuário

Poka
Usuário Nível 4

Usuário Nível 4
 
Mensagens: 513
Data de registro: 25 Out 2004 21:26
Cidade/Estado: Leme/SP
Curtiu: 0 vez
Mens.Curtidas: 23 vezes

Próximo



Retornar para SQL

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 7 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro