MySQL: select com soma de dados

Fórum sobre Banco de Dados e RDDs para Clipper/[x]Harbour.

Moderador: Moderadores

cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

MySQL: select com soma de dados

Mensagem por cjp »

Pessoal,

Tenho uma tabela num banco de dados MySQL que tem, entre outros, os seguintes campos:

COMPVENDA
CODIGO

Preciso fazer um select que me entregue uma lista dos códigos (campo CODIGO) em que a soma de todos os campos COMPVENDA em todos os registros seja maior que zero.

Tentei usar sum(compvenda), mas está me retornando Erro SQL 1111. Pesquisei este erro, mas ele é muito genérico, não consegui aplicar as sugestões à minha aplicação.

Pelo que vi no manual do MySQL, a SUM não faz exatamente o que eu quero.

Sei que daria para fazer uma pesquisa para cada código, somando os campos COMPVENDA de cada uma separadamente. Mas o que eu preciso é fazer tudo num só select.

Alguém poderia me auxiliar?
Inacio de Carvalho Neto
Avatar do usuário
janio
Colaborador
Colaborador
Mensagens: 1846
Registrado em: 06 Jul 2004 07:43
Localização: UBAJARA - CE

MySQL: select com soma de dados

Mensagem por janio »

Select CODIGO, SUM(COMPVENDA) as SOMA from TABELA group by CODIGO having SOMA > 0
fui...
e-mail:janioaguiar@yahoo.com.br
msn: janio_aguiar@hotmail.com
xHarbour1.2.1/Harbour3.2 + wvg + hwgui + Mediator + MySql
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

MySQL: select com soma de dados

Mensagem por cjp »

Funcionou assim. Muito obrigado.
Inacio de Carvalho Neto
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

MySQL: select com soma de dados

Mensagem por cjp »

Pessoal, tenho uma outra dúvida nesta mesma tabela, que também se refere a um select que estou tentando fazer.

A tabela tem os seguintes campos (entre outros):

Código: Selecionar todos

CODIGO
DTCOTACAO
HRCOTACAO
COTACAO
COMPVENDA
Preciso fazer um select que me retorne a lista dos códigos (campo CODIGO) dessa tabela em ordem crescente de cadastro da última cotação de cada código.

Um select simples assim (select codigo where cotacao>0 order by dtcotacao,hrcotacao) não serve, porque ele vai colocar em primeiro lugar o código cadastrado, por exemplo, em 01/01/16, mesmo que depois tenha sido cadastrado outra cotação do mesmo código em 09/02/17.

Então, eu precisaria pegar código a código, ver qual foi o último cadastro de cotação desse código, e daí sim colocar em ordem de data.

Tem como fazer isso em apenas um select?
Inacio de Carvalho Neto
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

MySQL: select com soma de dados

Mensagem por alxsts »

Olá!

Tem sim. Pesquise no Google que tem muitos exemplos. Pesquise "select max in group".
[]´s
Alexandre Santos (AlxSts)
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

MySQL: select com soma de dados

Mensagem por cjp »

Realmente achei. Muito obrigado.

Mas estou com dois problemas:

1) da forma como estou fazendo, está dando o seguinte erro:

Código: Selecionar todos

Erro SQL (1111): Invalid use of group function
O select com erro está assim:

Código: Selecionar todos

select codigo,cotacao,max(dtcotacao) as data from tabela where compvenda<>0 and max(dtcotacao)<'2016-12-30' group by codigo order by max(dtcotacao)
Tem várias informações na internet sobre esse erro, mas não vi nada que tivesse a ver com o meu caso.

Percebi que, tirando o "max(dtcotacao)<'2016-12-30'", funciona. Só que não vi nenhum erro nessa expressão, já que dtcotacao é um campo da tabela do tipo DATE.







2) tirando o "max(dtcotacao)<'2016-12-30'", como disse, o select funciona, mas tem um erro: ele lista na ordem do max(dtcotacao) considerando apenas os códigos com compvenda diferente de zero. Sei que eu mesmo coloquei o "where compvenda<>0", mas a intenção seria listar apenas os que tem compvenda diferente zero, mas na ordem do max(dtcotacao) igual a zero.

Sei que ficou confuso, vou tentar explicar melhor com exemplos:

Imagine que a tabela tenha os seguintes dados:

Código: Selecionar todos

CODIGO      DTCOTACAO      COTACAO     COMPVENDA
ABCD1       2016-01-01       1,00           0
EFGH2       2016-02-01       0,50           0
ABCD1       2016-05-01       2,00           0
EFGH2       2016-06-20       5,00           0
ABCD1       2016-07-22       3,00           0
ABCD1       2016-08-31       1,50         100
ABCD1       2016-12-10       2,50           0
Da forma como eu fiz o select, ele está retornando o max(dtcotacao) de ABCD1 em 2016-08-31, mas eu gostaria que retornasse em 2016-12-10.

Talvez me perguntem: mas então para que o "where compvenda<>0"? Resposta simples: para não incluir na lista o EFGH2, que não tem nenhum compvenda diferente de zero. Me entende?

Pode me ajudar?
Inacio de Carvalho Neto
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

MySQL: select com soma de dados

Mensagem por alxsts »

Olá!
cjp escreveu:Me entende?
Espero ter entendido...

Veja o resultado:
cjp.PNG
Segue o código SQL:

Código: Selecionar todos

CREATE TABLE 'tbTeste' (
	'codigo' CHAR(5) NOT NULL,
	'dtcotacao' DATE NULL,
	'cotacao' DECIMAL(7,2) NULL,
	'compvenda' INT NULL
)
COMMENT='Teste CJP'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

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

INSERT INTO tbTeste (CODIGO, DTCOTACAO, COTACAO, COMPVENDA) VALUES 
 ('ABCD1', '2016-01-01', 1.00, 0)
,('EFGH2', '2016-02-01', 0.50, 0)
,('ABCD1', '2016-05-01', 2.00, 0)
,('EFGH2', '2016-06-20', 5.00, 0)
,('ABCD1', '2016-07-22', 3.00, 0)
,('ABCD1', '2016-08-31', 1.50, 100)
,('ABCD1', '2016-12-10', 2.50, 0)

#-------------------------------------------------------------------------------

SELECT t1.codigo, t2.dtcotacao, t1.cotacao, t1.compvenda
  FROM tbTeste t1
  JOIN ( SELECT codigo, Max( dtcotacao ) As dtcotacao
           FROM tbTeste
          WHERE codigo = codigo) as t2
    ON t1.codigo = t2.codigo 
 WHERE t1.compvenda <> 0                                            
 ORDER BY t2.dtcotacao                                            

#-------------------------------------------------------------------------------
Informe se é isto mesmo que precisa.

SQLSELECTMAXINGROUP
[]´s
Alexandre Santos (AlxSts)
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

MySQL: select com soma de dados

Mensagem por cjp »

Sim, parece que é isso mesmo que eu quero.

Vou ter que estudar essa JOIN e t1 e t2 para entender. Não conhecia isso.

Por enquanto, muito obrigado.
Inacio de Carvalho Neto
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

MySQL: select com soma de dados

Mensagem por alxsts »

Olá!

No exemplo acima, t1 e t2 são apelidos (aliases) de tabela. As colunas também podem receber apelidos como em

Código: Selecionar todos

SELECT CustName AS 'Cód. Cliente' FROM tbCustomes cust
Isto é opcional mas ajuda muito. Veja exemplos: SQL Aliases

Já a questão dos JOINs deve ser muito estudada pois é fundamental em qualquer sistema gerenciador de banco de dados (SGBD). Como o próprio nome já diz, o sistema é relacional. O relacionamento entre as tabelas é feito por JOINs (junções). Para melhor performance, é importante que todas as tabelas possuam suas chaves primárias (primary keys ou PK) definidas e que os relacionamentos também sejam criados através da definição de chaves estrangeiras (foreign keys ou FK). Veja Basic SQL Join Types
[]´s
Alexandre Santos (AlxSts)
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

MySQL: select com soma de dados

Mensagem por cjp »

A parte do alias eu entendi bem.

A do join, na teoria, entendi.

Mas, ao tentar aplicar o teu exemplo à minha tabela, não funcionou como eu esperava, e não sei dizer bem o porquê.

Veja se eu estou correto, por favor: vc criou virtualmente uma segunda tabela (t2), com todos os registros, colocando max(dtcotacao) em dtcotacao; é isso?

E depois fez um select fazendo a junção da tabela original (chamada de t1) com o campo dtcotacao de t2 e os demais campos de t1; estou certo?

Não vi nesse exemplo onde ficaria o meu 'max(dtcotacao)<'2016-12-30'. Também não vi nele o group by.

Minha ideia seria retornar todos os registros que têm compvenda<>0 e que max(dtcotacao) seja menor que a data x (no exemplo que dei: 2016-12-30). Mas usando o teu exemplo na minha tabela, ele está retornando apenas um código, que aparece duplicado.
Inacio de Carvalho Neto
tonyedented
Usuário Nível 1
Usuário Nível 1
Mensagens: 1
Registrado em: 19 Abr 2022 12:53
Localização: Bengaluru

MySQL: select com soma de dados

Mensagem por tonyedented »

Alias in SQL is basically a temporary name that is given to a table or a column while writing a query. This is usually done when the column or the table names are long, so in order to render more readability, the alias is given. The alias in SQL is a temporary change and only exists till the duration of that query.

For column alias

Código: Selecionar todos

SELECT column_name AS alias_name
FROM table_name;
For table alias

Código: Selecionar todos

SELECT column_1,column_2...
FROM table_name AS alias_name;
To know more refer to this article: https://www.scaler.com/topics/alias-in-sql/
carlos moc
Usuário Nível 2
Usuário Nível 2
Mensagens: 68
Registrado em: 16 Out 2017 16:00
Localização: Montes Claros MG - Zap (38)99831-5319

MySQL: select com soma de dados

Mensagem por carlos moc »

Vou dar um pitaco aqui, estou à 16 anos com o mysql, tenho um sistema hospitalar que a base já passa de 1TB , são muitos os relatórios eu tive problemas ao gerar alguns usando (inner join,left join, group by) de chegar ao ponto de parar o sistema enquanto os relatórios eram processados, foi só eliminar essas cláusulas e resolveu.

Lembrando que é só um pitaco .
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

MySQL: select com soma de dados

Mensagem por alxsts »

Olá!

SGBD- R - Sistema Gerenciador de Banco de Dados - Relacional.

O sistema, como o próprio nome sugere, é baseado no relacionamento de seus objetos, principalmente as tabelas. Este relacionamento é obtido através de JOINS. Se for para eliminar os JOINS de um SGBD- R, melhor continuar com DBF...

Se o teu sistema ficou lento, provavelmente houve alguma falha na modelagem de dados. Revise índices, crescimento de tabelas, excesso de triggers...

Estude o manual em anexo (em Inglês)
Anexos
Data_Modeling_and_Relational_Database_De.pdf
Oracle - Manual de Modelagem de Dados e Projeto de Bancos de Dados Relacionais
(1.4 MiB) Baixado 301 vezes
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MySQL: select com soma de dados

Mensagem por JoséQuintas »

Só lembrando:
Tive um problema de lentidão recente, e o problema era codepage errada, vinda de mudanças de versão MySQL.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
carlos moc
Usuário Nível 2
Usuário Nível 2
Mensagens: 68
Registrado em: 16 Out 2017 16:00
Localização: Montes Claros MG - Zap (38)99831-5319

MySQL: select com soma de dados

Mensagem por carlos moc »

Não uso triggers, as tabelas as quais me refiro são (pacientes 250.000 registros) com uma tabela de histórico de movimentações(histórico do paciente dentro da unidade hospitalar) mais de 1.250.000 registros , lembrando que essa tabela de pacientes ela é acessada para escrita/consulta o tempo todo por 230 terminais são 720 leitos ocupados diariamente , nossa taxa de ocupação é de 90%, 8 km de cabos de rede, e ainda vem o administrativo, plano de saúde, faturamento.

Tem noção o que é isso ? cai pra dentro, ai vc vai ficar de cabeça branca logo logo.kkk


falei que era só um pitaco.

O que é bom pra mim pode ser que não seja bom para os outros.
Responder