Ir para conteúdo
Fórum Script Brasil
  • 0

(Resolvido) SELECT SUM pelo VB-6 (Com Filtro)


Danleonhart

Pergunta

É possível fazer em um único SELECT três somas de campos através de filtragem ?

É assim:

Tenho uma Tabela com 6 Campos...um dos campos é chamado "Tipo", onde é determinado por três tipos: Brim, Índigo e Lavagem...

Tenho outro Campo chamado "Metragem" com os "valores"...então, para somar apenas um "Tipo" faço assim:

Set Rs = Con.Execute("SELECT SUM(Metragem) As SomaTotal From Tabela WHERE Tipo='Brim'")

Ele filtra, e soma apenas os dados com "Tipo" setado em "Brim" :closedeyes: ;

quero apresentar um relatório com os resultados das somas dos diferentes "Tipos" (Brim, Índigo e Lavado), então, se for fazer, terei de criar 3 RecordSet's... um para cada tipo se for seguir a ordem do raciocinio...

Quero saber se tem como eu fazer todas as somas "filtradas" em um único RecordSet :) .

Editado por Danleonhart
Link para o comentário
Compartilhar em outros sites

14 respostass a esta questão

Posts Recomendados

  • 0

você quer somar os tres tipos todos juntos ou quer somar separadamente mas trazer os tres no select??

se for td junto seria só isso:

SELECT SUM(Metragem) As SomaTotal From Tabela WHERE Tipo In ('Brim', 'Índigo', 'Lavagem')
o q seria o mesmo q:
SELECT SUM(Metragem) As SomaTotal From Tabela WHERE Tipo = 'Brim' OR Tipo = 'Índigo' OR Tipo = 'Lavagem'
se for pra agrupar separadamente, use group by (funciona com o exemplo do OR tb):
SELECT Tipo, SUM(Metragem) As SomaTotal From Tabela WHERE Tipo In ('Brim', 'Índigo', 'Lavagem') Group By Tipo

retorna duas colunas: o tipo e a soma da metragem dele.

Link para o comentário
Compartilhar em outros sites

  • 0

Kuroi,

Aqui não deu... :unsure:

Segundo o que deu para entender no link, ele vai agrupar em ordens os valores...estou tentando em um único select, somar os valores da coluna "Metragem" mas filtrando pelos diferentes tipos da coluna "Tipo"...ou seja, teria de me retornar três valores separados: X de Brim, Y de Índigo e Z de Lavados...

Link para o comentário
Compartilhar em outros sites

  • 0

mas é isso mesmo, use o terceiro codigo q passei.

cada uma das somas vai vir em registro separado. serao tres registros e você vai acessando os proximos com um .MoveNext()

qual banco você usa?? tenta executar o codigo direto no gerenciador pra visualizar o retorno q fica mais facil de entender.

Link para o comentário
Compartilhar em outros sites

  • 0

se você abrir o seu banco no access, for na parte de consultas, clicar em nova consulta, mudar pra modo sql, você pode digitar esse codigo e executar (clicando na exclamacao) q ele vai mostrar certinho qual o retorno:

SELECT Tipo, SUM(Metragem) As SomaTotal From Tabela WHERE Tipo In ('Brim', 'Índigo', 'Lavagem') Group By Tipo
mas um exemplo com o .MoveNext():
sql = "SELECT Tipo, SUM(Metragem) As SomaTotal From Tabela WHERE Tipo In ('Brim', 'Índigo', 'Lavagem') Group By Tipo"
Set cn = rs.Execute(sql)

Text1.Text = ""

Do While Not rs.EOF
    Text1.Text = Text1.Text & rs!Tipo & _
        ": " & rs!SomaTotal & vbCrLf

    rs.MoveNext
Loop[/code]

no caso, Text1 é um TextBox com MultiLine = True.

Link para o comentário
Compartilhar em outros sites

  • 0

Kuroi...

Nesta filtragem com soma de campos que faço algumas vezes o resultado será "nulo", e neste caso ocorre o erro:

-----------------------------------

Run Time -2147217887:

Uma coluna não anulável não pode ser atualizada para Null.

-----------------------------------

No script é grifado justamente o campo que retorna o resultado da soma.

Tentei tratar assim:

If IsNull(R(3)("VInd")) Then
R(3)("VInd") = ""
End If
Também fiz assim:
If IsNull(R(3)("VInd")) Then
R(3)("VInd") = "0.00"
End If

Mas o erro continua aparecendo...

Lembro, que só ocorre quando a filtragem não encontra nada conforme exijo na query (tipo: Somar tudo com "Tipo='Índigo'", e não haver nada com Tipo = Índigo)... no mais funciona normal...

isso me pegou mesmo... :blink:

Link para o comentário
Compartilhar em outros sites

  • 0

R(3) é um dos RecordSet...quero lembrar que utilizo 3, então fiz um Array:

Dim R(1 To 3) as New ADODB.RecordSet
O erro acontece na linha do resultado do "SELECT SUM" com filtragem, ele retorna o resultado da soma de uma coluna, mas só faz essa soma "onde" o "Tipo" for "Indigo" por exemplo...porém se ele não encontrar, vai retornar nulo...ou seja, "VInd" é o resultado do "SELECT SUM":
Set R(3) = Con.Execute("SELECT SUM(Metragem) As VInd From Tabela WHERE Data=#" & DT & "# AND Setor='" & ST & "' AND Tipo='Índigo'")
Então o resultado do RecordSet é:
R(3)("VInd")

Porém, haverá situações em que ele irá retornar "vazio", pois vai depender da variavel "DT" (que é uma Data).

Deu para entender ? :unsure:

Editado por Danleonhart
Link para o comentário
Compartilhar em outros sites

  • 0

mas o erro é na linha do execute?? olhando aqui parece tudo certo. o unico problema q encontrei foi esse aqui:

If IsNull(R(3)("VInd")) Then
R(3)("VInd") = "0.00" '<---- Essa linha aqui
End If[/code] o campo VInd não existe no banco, ele é um campo calculado. ou seja, não é uma consulta atualizavel, acho q ele não vai aceitar isso ai não. você deveria tratar isso de outro jeito. teste com o IsNull() na hora de mostrar no programa (na label, textbox, ou em qualquer outro lugar q você quiser). não sei se tem formas simples de tratar direto no sql... tem aqui uns jeitos q eu costumo fazer, mas eu não gosto muito porque eles deixam a consulta bem comprida e complicada pra alterar. mas use-os caso você ache q fique mais simples do q tratar externamente (ou em casos onde o tratamento externo não seja possivel). o mais simples seria com Iif() (no caso do access):
[code]SELECT IIf(IsNull(SUM(Metragem)), 0, SUM(Metragem)) As VInd From Tabela WHERE Data=#" & DT & "# AND Setor='" & ST & "' AND Tipo='Índigo'
outras ideias:
SELECT SUM(Metragem) As VInd From (Select Metragem From Tabela WHERE Data=#" & DT & "# AND Setor='" & ST & "' AND Tipo='Índigo' UNION ALL Select 0 From Tabela)
SELECT CDbl('0' & SUM(Metragem)) As VInd From Tabela WHERE Data=#" & DT & "# AND Setor='" & ST & "' AND Tipo='Índigo'

eu imagino q aquele do IIf() seja o mais rapido de executar. só não tenho certeza pelo fato de a gente chamar o Sum() duas vezes. eu acredito na possibilidade de o access somar só uma vez e colocar o valor da primeira soma logo no retorno da segunda. agora caso ele faca a soma duas vezes, então esse seria o mais lento. pra descobrir, só pegando um banco gde e testar os exemplos, contando o tempo de demora.

quanto aos outros exemplos, não tenho certeza em relacao a como o access le as subconsultas, então não sei dizer ao certo sobre o segundo. mas aquele do CDbl(), apesar de fazer duas conversoes, caso o retorno seja só um registro, como é o caso, a diferenca deve ser minima.

só lembre de trocar o CDbl() (conversao pra tipo Double (duplo)) para o verdadeiro tipo q você quiser converter (exemplo, CLng(), caso seja do tipo Long (inteiro longo)).

Link para o comentário
Compartilhar em outros sites

  • 0

Kuroi...

Fiz algumas alterações aqui...o importante é que está funcionando redondo, sem precisar de " On Error Resume Next " :)

Então, resolví colocar os resultados em "variáveis" e tratar os resultados antes de aplicá-los onde desejo...

Na verdade, mostrei apenas a parte do código que estava com problema...pois estou a utilizar o "Active Reports" como forma de apresentar relatórios e opção de impressão com exportação para PDF, Excel, RTF e até Texto...

Faço todas consultas necessárias e jogo os resultados em outro RecordSet, só que "desconectado"... para assim fazer o lançamento no "Active Reports"...

Se tem forma mais simple, deve ter...mas fiz assim e funciona ! :D :

Public Sub FiltroSetor()
Printer.Restart
Dim DT As Variant
Dim VBrim, VInd
Dim ST, TP, Filtro As String
Dim R(1 To 3) As New ADODB.Recordset
DT = Format(Mk_Data.Text, "YYYY-MM-DD")
ST = Cb_Set.Text

Abb
Set R(1) = Con.Execute("SELECT SUM(Metragem) As SomaBrim From Ting WHERE Data=#" & DT _
& "# AND Setor='" & ST & "' AND Tipo='Brim'")

If IsNull(R(1)("SomaBrim")) Then
VBrim = "0,00"
Else
VBrim = R(1)("SomaBrim")
End If

Set R(1) = Con.Execute("SELECT SUM(Metragem) As SomaInd From Ting WHERE Data=#" & DT _
& "# AND Setor='" & ST & "' AND Tipo='Índigo'")

If IsNull(R(2)("SomaInd")) Then
VInd = "0,00"
Else
VInd = R(2)("SomaInd")
End If

Set R(3) = Con.Execute("SELECT * FROM Ting WHERE Data=#" & DT & "# AND Setor='" & ST & "'")

Dim Rst As ADODB.Recordset
Set Rst = New ADODB.Recordset
Rst.ActiveConnection = Nothing

With Rst
       .Fields.Append "vData", adDate, 8
       .Fields.Append "vSetor", adVarChar, 50
       .Fields.Append "TBrim", adVarChar, 50
       .Fields.Append "TInd", adVarChar, 50
       .Fields.Append "STotal", adVarChar, 50
       .Open
       
       .AddNew
       .Fields("vData") = DT
       .Fields("vSetor") = ST
       .Fields("TBrim") = VBrim
       .Fields("TInd") = VInd
       .Fields("STotal") = VBrim + VInd
       .Update
End With

With Printer
           .ADO.ConnectionString = Con.ConnectionString
           .ADO.Recordset = Rst
           .txtSoma.DataField = "STotal"
           .txtData.DataField = "vData"
           .txtSetor.DataField = "vSetor"
           .TBrim.DataField = "TBrim"
           .TInd.DataField = "TInd"
           
             .txtMaq.Text = ""
             .txtTipo.Text = ""
             .txtMet.Text = ""
             
              Do Until R(3).EOF
                   .txtMaq.Text = .txtMaq.Text & R(3)("Maquina") & vbNewLine
                   .txtTipo.Text = .txtTipo.Text & R(3)("Tipo") & vbNewLine
                   .txtMet.Text = .txtMet.Text & R(3)("Metragem") & vbNewLine
                    R(3).MoveNext
              Loop
    nDia = Format(Now, " DDDD ")
    Dia = Format(Now, " DD ")
    Mes = Format(Now, " MMMM ")
    Ano = Format(Now, " YYYY")
            .LbHoje.Caption = nDia & Dia & "de" & Mes & "de" & Ano      
End With
ARV1.ReportSource = Printer
End Sub

Obrigado pelas dicas mais uma vez !

;)

Editado por Danleonhart
Link para o comentário
Compartilhar em outros sites

  • 0
não sei se tem formas simples de tratar direto no sql... tem aqui uns jeitos q eu costumo fazer, mas eu não gosto muito porque eles deixam a consulta bem comprida e complicada pra alterar. mas use-os caso você ache q fique mais simples do q tratar externamente (ou em casos onde o tratamento externo não seja possivel).

lendo um post o MrMalJ, descobri q existe uma funcao chamada Nz(), q simplifica aquele iif() q passei e q teria me ajudado muito nesses ultimos 7 anos, se eu a tivesse conhecido antes. mas por incompetencia, eu a ignorava completamente...

a unica desvantagem q encontrei nessa funcao é q ela converte o campo pra string, o q deve atrapalhar quando for pra trabalhar com numeros. sendo assim, vai ser necessario fazer uma conversao depois de utiliza-la:

SELECT CDbl(Nz(SUM(Metragem), 0)) As VInd From Tabela WHERE Data=#" & DT & "# AND Setor='" & ST & "' AND Tipo='Índigo'

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,5k
×
×
  • Criar Novo...