Usuário com melhor resposta
Erro 8120 na hora de fazer um select com Group By

Pergunta
-
Boa noite Srs.,
Preciso de ajuda com o seguinte ponto. Tenho uma tabela que possui as colunas abaixo:
tbl_Retrabalho
IDWR(chave primária)
Data as Date
Item as varchar
FluxoValor as varchar
TipoRetrabalho as varchar
Tempo as int
e como exemplo tenho os seguintes dados nesse planilha:
IDWR Data Item FluxoValor TipoRetrabalho Tempo 1 10/12/2016 66444888 Injeção Nitrogênio 10 2 11/12/2016 66444888 Injeção Nitrogênio 12 3 12/12/2016 66444888 Compressão Nitrogênio 6 4 13/12/2016 66444888 Compressão Nitrogênio 6 5 14/12/2016 66444888 Compressão Pós cura 16 Estou precisando fazer um Select para aparecer os Dados da Seguinte forma:
FluxoValor TipoRetrabalho SomaTempo Compressão Nitrogênio 12 Compressão Pós Cura 16 Injeção Nitrogênio 22 ou seja, agrupar por fluxovalor e TipoRetrabalho e somar os valor de tempo correspondente.
Estou usando a seguinte clausula:
Select FluxoValor, TipoRetrabalho, Sum(Tempo) as SomaTempo
from tbl_Retrabalho
Group By FluxoValor, TipoRetrabalho
mas gera o seguinte erro:
Msg 8120, Level 16, State 1, Line 3
Column 'tbl_Retrabalho.TipoRetrabalho' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
O que devo fazer para corrigir? Agluém tem uma solução?
Já tentei tirar o Sum(Tempo) mas gera o mesmo erro.
Agradeço muito por uma ajuda,
Damião
Respostas
-
Então o seu problema com a questão do group by parece que está resolvido. pela query
SELECT FluxoValor, TipoRetrabalho, Sum(Tempo) as SomaTempo from tbl_Retrabalho group by FluxoValor, TipoRetrabalho;
partindo da segunda questão de uma lida nesse artigo para entender as diferenças entre where e having
e como usar este, leia também o artigo parte 1.
http://www.devmedia.com.br/exemplos-com-group-by-e-com-a-clausula-having-totalizando-dados-sql-server-2008-parte-2/19839
em resumo , o Having atua sobre o resultado gerado pelo Group By, logo ele vai filtrar os dados agrupados.
para isso vc para aplicar o filtro de datas deveria ter mais uma coluna data no seu select ,
segue um exemplo , que primeiro aplica o filtro de datas e segundo faz o agrupamento
exemplo 1: acrescentando uma coluna data
SELECT FluxoValor ,
TipoRetrabalho ,
Data = MAX(Data),
SUM(Tempo) AS SomaTempo
FROM @Table
GROUP BY FluxoValor ,
TipoRetrabalho
HAVING MAX(Data) BETWEEN @DataInicio AND @DataTerminoou agrupando o seu resultado por data.
SELECT FluxoValor ,
TipoRetrabalho ,
Data = Data,
SUM(Tempo) AS SomaTempo
FROM @Table
GROUP BY FluxoValor ,
TipoRetrabalho,DataHAVING Data BETWEEN @DataInicio AND @DataTermino
Mas aqui abaixo tem uma opção boa, onde vc tem um resultado que aplica o filtro de data e após gera o agrupamento
DECLARE @DataInicio DATE ='10/12/2016',@DataTermino DATE ='12/12/2016' ; WITH Dados AS ( SELECT T.IDWR , T.Data , T.Item , T.FluxoValor , T.TipoRetrabalho , T.Tempo FROM @Table AS T WHERE CAST(T.Data AS DATE) BETWEEN @DataInicio AND @DataTermino ) SELECT T.FluxoValor , T.TipoRetrabalho , [Soma tempo] = SUM(T.Tempo) FROM Dados AS T GROUP BY T.FluxoValor , T.TipoRetrabalho ORDER BY [Soma tempo];
Wesley Neves
- Marcado como Resposta damiao.antunes1 domingo, 18 de dezembro de 2016 12:31
-
Deleted
- Marcado como Resposta damiao.antunes1 domingo, 18 de dezembro de 2016 12:31
Todas as Respostas
-
Com os dados que vc postou segue o exemplo
DECLARE @Table TABLE ( IDWR INT PRIMARY KEY IDENTITY(1, 1) , Data VARCHAR(MAX) , Item INT DEFAULT ( 66444888 ) , FluxoValor VARCHAR(MAX) , TipoRetrabalho VARCHAR(20) , Tempo INT ); /* IDWR Data Item FluxoValor TipoRetrabalho Tempo 1 10/12/2016 66444888 Injeção Nitrogênio 10 2 11/12/2016 66444888 Injeção Nitrogênio 12 3 12/12/2016 66444888 Compressão Nitrogênio 6 4 13/12/2016 66444888 Compressão Nitrogênio 6 5 14/12/2016 66444888 Compressão Pós cura 16 */ INSERT INTO @Table ( Data, Item, FluxoValor, TipoRetrabalho, Tempo ) VALUES ( '10/12/2016', DEFAULT, 'Injeção', 'Nitrogênio', 10 ), ( '11/12/2016', DEFAULT, 'Injeção', 'Nitrogênio', 12 ), ( '12/12/2016', DEFAULT, 'Compressão', 'Nitrogênio', 6 ), ( '13/12/2016', DEFAULT, 'Compressão', 'Nitrogênio', 6 ), ( '14/12/2016', DEFAULT, 'Compressão', 'Pós cura', 16 ); /* FluxoValor TipoRetrabalho SomaTempo Compressão Nitrogênio 12 Compressão Pós Cura 16 Injeção Nitrogênio 22 */ SELECT T.FluxoValor , T.TipoRetrabalho , [Soma tempo] = SUM(T.Tempo) FROM @Table AS T GROUP BY T.FluxoValor , T.TipoRetrabalho ORDER BY [Soma tempo];
Acredito que o seu problema seja outro pois o seu select que vc postou ,aqui funcionou corretamente
usando o seu select(apenas troquei para a tabela declarada.
SELECT FluxoValor ,
TipoRetrabalho ,
SUM(Tempo) AS SomaTempo
FROM @Table
GROUP BY FluxoValor ,
TipoRetrabalho;Wesley Neves
-
-
José,
Segue a tabela como está no meu SQL Server:
IDWR (PK,int,not null)
Dat (Date, not null)
Item (varchar(30), not null)
TipoDoc (Varchar(2), not null)
NDoc (int, not null)
Conformidade (varchar(255), not null)
TipoRetrabalho(varchar(255),not null)
QtdBoas (int, not null)
QtdRuins (int, not null)
Tempo (int, not null)
FluxoValor (varchar(50), not null)
e segue o descrito com o comando print @@version:
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64)
Apr 2 2010 15:48:46
Copyright (c) Microsoft Corporation
Express Edition with Advanced Services (64-bit) on Windows NT 6.1 <X64> (Build 7600: )
José,
Mas usei exatamente o código declarado pelo Wesley Neves e funcionou...sabe me dizer o motivo?
Muito obrigado José e Wesley pela ajuda,
-
-
José,
Realmente o código #1 dá o erro que mostrou, mas para os códigos #2 e #3 funciona perfeitamente.
Agora preciso de outra ajuda nesse mesmo código. Estou utilizando o Visual Studio para criar um programa para a empresa que trabalho, e nessa consulta preciso colocar uma clausula where para filtrar os dados pelo campo DAT da tabela, ou seja, quero que faça essa consulta somente entre duas datas que o usuário escolher.
Estou tentando com o seguinte código código (criando uma procedure para buscar depois no VB.net:
Create Procedure TotalRetrabalho
@DataInicial date,
@DaaFinal date
as
Begin
Select T.FluxoValor, T.TipoRetrabalho, [SomaTempo] = sum(T.Tempo)
From tbl_Retrabalho as T
Group By T.FluxoValor, T.TipoRetrabalho
Having T.Dat>=@DatInicial and T.Dat <=@DatFinal
Order BY T.FluxoValor, T.TipoRetrabalho
END
Mas gera o seguinte erro:
Msg 137, Level 15, State 2, Procedure TotalRetrabalho, Line 15 (linha do Having)
Must declare the scalar variable "@DataIncial".
Se eu removo o Having funciona perfeitamente mas não consigo filtrar pelas datas, se troco o Having pelo WHERE da um erro na palavra Where....
Como posso fazer essa consulta filtrando pelas datas?
Muito obrigado,
-
Então o seu problema com a questão do group by parece que está resolvido. pela query
SELECT FluxoValor, TipoRetrabalho, Sum(Tempo) as SomaTempo from tbl_Retrabalho group by FluxoValor, TipoRetrabalho;
partindo da segunda questão de uma lida nesse artigo para entender as diferenças entre where e having
e como usar este, leia também o artigo parte 1.
http://www.devmedia.com.br/exemplos-com-group-by-e-com-a-clausula-having-totalizando-dados-sql-server-2008-parte-2/19839
em resumo , o Having atua sobre o resultado gerado pelo Group By, logo ele vai filtrar os dados agrupados.
para isso vc para aplicar o filtro de datas deveria ter mais uma coluna data no seu select ,
segue um exemplo , que primeiro aplica o filtro de datas e segundo faz o agrupamento
exemplo 1: acrescentando uma coluna data
SELECT FluxoValor ,
TipoRetrabalho ,
Data = MAX(Data),
SUM(Tempo) AS SomaTempo
FROM @Table
GROUP BY FluxoValor ,
TipoRetrabalho
HAVING MAX(Data) BETWEEN @DataInicio AND @DataTerminoou agrupando o seu resultado por data.
SELECT FluxoValor ,
TipoRetrabalho ,
Data = Data,
SUM(Tempo) AS SomaTempo
FROM @Table
GROUP BY FluxoValor ,
TipoRetrabalho,DataHAVING Data BETWEEN @DataInicio AND @DataTermino
Mas aqui abaixo tem uma opção boa, onde vc tem um resultado que aplica o filtro de data e após gera o agrupamento
DECLARE @DataInicio DATE ='10/12/2016',@DataTermino DATE ='12/12/2016' ; WITH Dados AS ( SELECT T.IDWR , T.Data , T.Item , T.FluxoValor , T.TipoRetrabalho , T.Tempo FROM @Table AS T WHERE CAST(T.Data AS DATE) BETWEEN @DataInicio AND @DataTermino ) SELECT T.FluxoValor , T.TipoRetrabalho , [Soma tempo] = SUM(T.Tempo) FROM Dados AS T GROUP BY T.FluxoValor , T.TipoRetrabalho ORDER BY [Soma tempo];
Wesley Neves
- Marcado como Resposta damiao.antunes1 domingo, 18 de dezembro de 2016 12:31
-
Deleted
- Marcado como Resposta damiao.antunes1 domingo, 18 de dezembro de 2016 12:31
-