none
Comando Max retornando mais de uma linha RRS feed

  • Pergunta

  • Pessoal, boa tarde!

    Tenho uma tabela com os seguintes campos:

    empresa   ind_numero    dt_de                         valor              data_alter                   hora_alter
    -------       ----------        -----------------------   ---------------- -----------------------     ----------
    3188         2                  2011-07-15 00:00:00  1.574300        2011-07-18 00:00:00   932
    3188         2                  2011-07-18 00:00:00  1.582800        2011-07-19 00:00:00   1407
    3187         2                  2011-07-18 00:00:00  1.582800        2011-07-19 00:00:00   1407

    Eu preciso pegar sempre o último valor informado na tabela.

    Tentei utilizar o seguinte comando:

    SELECT EMPRESA, IND_NUMERO, Max(DT_DE) AS DT_ID, Max(GETDate()) AS DT_ATUAL
    FROM ABIN
    GROUP BY EMPRESA, IND_NUMERO
    HAVING (((EMPRESA)=3187) AND ((IND_NUMERO)=2));


    Que me retornou o seguinte:

    EMPRESA     IND_NUMERO   DT_ID                           DT_ATUAL
    -------         ----------         -----------------------      -----------------------
    3187           2                   2011-07-18 00:00:00     2011-07-19 14:50:13.460

     

    Quando incluo o campo valor na consulta ao invés de retornar uma única linha (como a de cima + o campo valor) aparecem várias linhas, como se eu não tivesse utilizado o MAX.

    SELECT EMPRESA, IND_NUMERO, Max(DT_DE) AS DT_ID, Max(GETDate()) AS DT_ATUAL, valor
    FROM ABIN
    GROUP BY EMPRESA, IND_NUMERO, valor
    HAVING (((EMPRESA)=3187) AND ((IND_NUMERO)=2));

    Alguém pode me ajudar?

    Obrigada.

    Êmili.

     

     

     

    terça-feira, 19 de julho de 2011 18:02

Respostas

  • Olá Emili, tudo bem?

     

    Tem alguns problemas no seu SQL, vou citá-los depois explicar como fazer:

    - Não precisa de Max(GetDate()), getdate será sempre a mesma data, basta utilizar então getDate()
    - Pode-se (e eu recomendo) trocar o HAVING por WHERE.

    Quando você inclui o campo valor e agrupa os resultados, o SQL vai trazer todos os valores DIFERENTES que encontra.

     

    Para resolver vc pode fazer assim:
     

    SELECT TOP 1 EMPRESA, IND_NUMERO, DT_DE AS DT_ID, GETDate() AS DT_ATUAL, valor
    FROM ABIN
    WHERE EMPRESA=3187 AND IND_NUMERO)=2
    AND  DT_DE = (select max(DT_DE) from abin B where abin.empresa = B.empresa and abin.ind_numero = B.ind_numero)

     

    Porque utilizar TOP 1?
    A coluna DT_DE pelo que vi no seu SQL pode repetir para várias linhas, portanto, sem o TOP 1 continuaria trazendo mais de uma linha caso essas possuirem o mesmo valor.

    Testa isso e posta o resultado aqui.

    Até mais =)

    quinta-feira, 21 de julho de 2011 19:14

Todas as Respostas

  • Emili,

     

    Voce precisa do ultimo valor em relação ao campo dt_de ou dt_alter?


    Fabrizzio A. Caputo
    Certificações: Oracle OCA 11g, MCITP SQL Server 2008 Implementation and Maintenance
    Blog Pessoal: www.fabrizziocaputo.wordpress.com
    Blog Empresa: www.tripletech.com.br/blog
    Twitter: @FabrizzioCaputo
    Email: fabrizzio.antoniaci@gmail.com
    terça-feira, 19 de julho de 2011 18:04
    Moderador
  • Boa Tarde,

    Não há nada de errado. O GROUP BY está funcionando corretamente. Quando você coloca a coluna VALOR, ela irá ser considerada para formar o GRUPO e nesse caso valores diferentes produzem novos grupos.

    Se você quer exibir o valor do grupo (e não simplesmente agrupá-lo), você terá que fazer um JOIN ou uma Subquery. O link abaixo dá mais detalhes:

    Como retornar o último registro por grupo ?
    http://gustavomaiaaguiar.wordpress.com/2009/01/11/como-retornar-o-ultimo-registro-por-grupo/

    Especificamente no seu exemplo, creio que sem uma unicidade em questão não é possível encontrar um resultado correto (quais seriam as chaves primárias ?). Veja que a combinação Empresa, IND_Numero e DT_DE não é única e nesse caso não há como exibir um só valor. Adicionalmente, MAX(GETDATE()) não é uma construção que faz sentido.

    [ ]s,

    Gustavo Maia Aguiar
    http://gustavomaiaaguiar.wordpress.com 


    Classifique as respostas. O seu feedback é imprescindível
    terça-feira, 19 de julho de 2011 18:29
  • Em relação ao campo dt_de
    terça-feira, 19 de julho de 2011 19:42
  • Gustavo, boa tarde!

    Na verdade preciso mesmo que a minha consulta retorne só uma linha (a última). Explico: essa tabela é uma tabela onde são cadastrados índices financeiros e eu necessito saber qual foi o último índice financeiro cadastrado (no dia) para pegar o valor e utilizá-lo em uma conta na minha aplicação.

    Por exemplo:

    empresa ind_numero dt_de                           valor                          data_alter                     hora_alter
    -------     ----------    -----------------------      ------------------------- ---------------------          ----------
    3188      2               2011-07-15 00:00:00     1.574300                   2011-07-18 00:00:00     932
    3188      2               2011-07-18 00:00:00     1.582800                   2011-07-19 00:00:00     1407
    3187      2               2011-07-18 00:00:00     1.582800                   2011-07-19 00:00:00     1407

    Nesse resultado eu preciso do registro de 19/07/11 às 14:07. Eu vou pegar o valor 1.5828 e multiplicá-lo por um outro valor dentro da aplicação.

    Estou estudando o link que você me passou e vou tentar fazer com uma subquery.

    Obrigada por enquanto.

    Êmili.

     

    terça-feira, 19 de julho de 2011 19:49
  • Êmili,

    Com base em qual coluna ou conjunto de colunas você deseja fazer o agrupamento?


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]
    quarta-feira, 20 de julho de 2011 00:35
  • Seria algo do tipo:

    SELECT

      A.*

    FROM

      ABIN A JOIN (SELECT

                     EMPRESA,

                     IND_NUMERO,

                     MaiorData = Max(DATA_ALTER),

                     MaiorHora = Max(HORA_ALTER),

                   FROM

                     ABIN

                   GROUP BY

                     EMPRESA,

                     IND_NUMERO) A2 ON (A.EMPRESA    = A2.EMPRESA)    AND

                                       (A.IND_NUMERO = A2.IND_NUMERO) AND

                                       (A.DATA_ALTER = A2.MaiorData)  AND

                                       (A.HORA_ALTER = A2.MaiorHora)

    WHERE

      (A.EMPRESA = 2)


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    quarta-feira, 20 de julho de 2011 02:43
  • Nas colunas DATA_ALTER e HORA_ALTER. Eu preciso do último registro do dia corrente inserido nessa tabela.
    quarta-feira, 20 de julho de 2011 18:30
  • Roberson, boa tarde!

    Obrigada pela dica. Testei a consulta que você propôs e ainda continuo na mesma situação. Explico:

    1) Ao consultar de acordo com o que você me passou recebo o seguinte resultado:

    SELECT A.*
    FROM  ABIN A
    JOIN (SELECT EMPRESA, IND_NUMERO,
          MaiorData = Max(DATA_ALTER),
          MaiorHora = Max(HORA_ALTER)
    FROM ABIN GROUP BY EMPRESA, IND_NUMERO) A2
    ON (A.EMPRESA    = A2.EMPRESA) AND
       (A.IND_NUMERO = A2.IND_NUMERO) AND
       (A.DATA_ALTER = A2.MaiorData)  AND
       (A.HORA_ALTER = A2.MaiorHora)
    WHERE (A.EMPRESA = 3187)

    EMPRESA  IND_NUMERO  DT_DE                            VALOR          DATA_ALTER               HORA_ALTER
    -------      ----------        --------------                   ------------    -----------------------    ----------    
    3187       8                   2005-01-31 00:00:00      1.000000      2005-08-26 00:00:00  1122     
    3187       2008              2005-01-31 00:00:00      1.000000      2005-08-26 00:00:00  1122   
    3187       10                 2011-04-12 00:00:00      1.580500      2011-05-31 00:00:00  1524      
    3187       2010              2011-04-12 00:00:00      1.580500     2011-05-31 00:00:00   1524     
    3187       11                 2011-04-12 00:00:00      2.298300     2011-05-31 00:00:00   1544     
    3187       2011             2011-04-12 00:00:00      2.298300     2011-05-31 00:00:00   1544     

    (6 row(s) affected)

    O resultado que a consulta está me trazendo não está correto, pois a última alteração feita nessa tabela não foi no dia 12/04/2011 e sim no dia 19/07/2011. Se eu consultar apenas utilizando a subquery da sua consulta eu consigo o resultado:

    SELECT EMPRESA, IND_NUMERO,
          MaiorData = Max(DATA_ALTER),
          MaiorHora = Max(HORA_ALTER)
    FROM ABIN
    where empresa = 3187
    GROUP BY EMPRESA, IND_NUMERO
    order by maiordata

    EMPRESA IND_NUMERO MaiorData               MaiorHora
    ------- ---------- ----------------------- ---------
    3187    2008       2005-08-26 00:00:00     1122
    3187    8          2005-08-26 00:00:00     1122
    3187    2006       2009-08-03 00:00:00     1614
    3187    6          2009-08-03 00:00:00     1614
    3187    2007       2011-03-22 00:00:00     1627
    3187    7          2011-03-22 00:00:00     1627
    3187    2011       2011-05-31 00:00:00     1544
    3187    10         2011-05-31 00:00:00     1524
    3187    2010       2011-05-31 00:00:00     1524
    3187    11         2011-05-31 00:00:00     1544
    3187    2001       2011-07-07 00:00:00     1757
    3187    1          2011-07-07 00:00:00     1757
    3187    2          2011-07-19 00:00:00     2111
    3187    2005       2011-07-19 00:00:00     1703
    3187    4          2011-07-19 00:00:00     1742
    3187    5          2011-07-19 00:00:00     1703
    3187    2003       2011-07-19 00:00:00     1826
    3187    2002       2011-07-19 00:00:00     2111
    3187    3          2011-07-19 00:00:00     1826
    3187    2004       2011-07-19 00:00:00     1742
    3187    9          2011-07-19 00:00:00     1704
    3187    2009       2011-07-19 00:00:00     1704

    (22 row(s) affected)

    Só que mesmo nessa segunda consulta, apesar de me trazer o último registro eu ainda não tenho o resultado que eu preciso, pois está faltando o campo valor na consulta. Quando incluo o campo valor na consulta passada por você o último registro data de 20/04/2011 e se incluo somente na subquery acima o último registro vem com a data correta (19/04/2011) porém aparecem na consulta todas as demais datas e eu gostaria que ao executá-la aparecesse somente uma única linha (a da última data). Mais ou menos assim:

     

    *FILTREI OS CAMPOS DATA_ALTER E IND_NUMERO SÓ PARA REDUZIR O NÚMERO DE REGISTROS NA RESPOSTA

    SELECT EMPRESA, IND_NUMERO, valor,
          MaiorData = Max(DATA_ALTER),
          MaiorHora = Max(HORA_ALTER)
    FROM ABIN
    where empresa = 3187 and data_alter between '2011-07-01' and '2011-07-30' and ind_numero = 2
    GROUP BY EMPRESA, IND_NUMERO, valor
    order by maiordata

    Retornasse:

    EMPRESA IND_NUMERO valor                                   MaiorData               MaiorHora
    ------- ---------- --------------------------------------- ----------------------- ---------
    3187    2          1.582800                                2011-07-19 00:00:00     1407

     

    E está retornando:

     

    EMPRESA IND_NUMERO valor                                   MaiorData               MaiorHora
    ------- ---------- --------------------------------------- ----------------------- ---------
    3187    2          1.558000                                2011-07-05 00:00:00     1220
    3187    2          1.559900                                2011-07-05 00:00:00     1218
    3187    2          1.561100                                2011-07-05 00:00:00     1217
    3187    2          1.563700                                2011-07-06 00:00:00     1544
    3187    2          1.566200                                2011-07-11 00:00:00     1522
    3187    2          1.563400                                2011-07-11 00:00:00     1526
    3187    2          1.558100                                2011-07-11 00:00:00     1524
    3187    2          1.579600                                2011-07-12 00:00:00     1443
    3187    2          1.576200                                2011-07-14 00:00:00     1703
    3187    2          1.577300                                2011-07-14 00:00:00     1702
    3187    2          1.572900                                2011-07-15 00:00:00     825
    3187    2          1.574300                                2011-07-18 00:00:00     932
    3187    2          1.582800                                2011-07-19 00:00:00     1407

    (13 row(s) affected)

    Não sei se consegui explicar direito, e também se isso é possível, mas é o que eu necessito.

     

    Obrigada.

     

    Êmili.

     

     

     

     

     

     

     

     

     

     

     

    quarta-feira, 20 de julho de 2011 20:20
  • Tche!! Select que tu escreveu não faz sentido...

    Tu quer um unico resultado???

    então pra que group by? pra que order by?

    SELECT MaiorData = Max(DATA_ALTER), MaiorHora = Max(HORA_ALTER), EMPRESA, IND_NUMERO, valor FROM ABIN
    where empresa = 3187 and data_alter between '2011-07-01' and '2011-07-30' and ind_numero = 2

    tenta assim sem essas treta toda ai só pra cumplica...

     

     


    Microsoft...
    quarta-feira, 20 de julho de 2011 21:01
  • Tenjor, bom dia!

    Se eu executar o select sem o group by dá a seguinte mensagem:

    Column 'ABIN.EMPRESA' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

    Por isso que eu utilizo. Não tenho certeza mas acredito que quando utiliza-se o MAX seja obrigatório a inserção do Group by. O Order coloquei só para facilitar a consulta.

    quinta-feira, 21 de julho de 2011 11:07
  • O problema está no IND_NUMERO, quando voce utiliza ele ai, ele vai criar um grupo pra cada, pois os valores dele são diferentes...

    oque voce poderia fazer é arrancar ele fora, e se for uma informação muito importante traga ele pra dentro de outra forma, fazendo um outro select ai dentro apenas pra retornar o IND_NUMERO do resultado desse MAX ai...

    Tenta ai... Essa é a idéia


    Microsoft...
    quinta-feira, 21 de julho de 2011 11:40
  • Olá Emili, tudo bem?

     

    Tem alguns problemas no seu SQL, vou citá-los depois explicar como fazer:

    - Não precisa de Max(GetDate()), getdate será sempre a mesma data, basta utilizar então getDate()
    - Pode-se (e eu recomendo) trocar o HAVING por WHERE.

    Quando você inclui o campo valor e agrupa os resultados, o SQL vai trazer todos os valores DIFERENTES que encontra.

     

    Para resolver vc pode fazer assim:
     

    SELECT TOP 1 EMPRESA, IND_NUMERO, DT_DE AS DT_ID, GETDate() AS DT_ATUAL, valor
    FROM ABIN
    WHERE EMPRESA=3187 AND IND_NUMERO)=2
    AND  DT_DE = (select max(DT_DE) from abin B where abin.empresa = B.empresa and abin.ind_numero = B.ind_numero)

     

    Porque utilizar TOP 1?
    A coluna DT_DE pelo que vi no seu SQL pode repetir para várias linhas, portanto, sem o TOP 1 continuaria trazendo mais de uma linha caso essas possuirem o mesmo valor.

    Testa isso e posta o resultado aqui.

    Até mais =)

    quinta-feira, 21 de julho de 2011 19:14
  • Êmili, esse seu campo de hora é de que tipo? É um inteiro?
    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    sexta-feira, 22 de julho de 2011 22:05
  • Êmili,

    Todas as vezes que utilizamos funções de agregação as colunas que não estão envolvidas nas funções devem ser declaradas na claúsula Group By, mas também toda regra pode ter uma exceções. Quando você utiliza somente funções de agregação sem outras colunas não é necessário utilizar o Group By.

    No Select anterior será necessário declarar a coluna que o SQL Server esta informando no group by.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]
    sábado, 23 de julho de 2011 00:46
  • Diego, boa tarde!

     

    Muito obrigada pela sua explicação.

    Seu select funcionou perfeitamente e resolveu meu problema.

    Obrigada mesmo!

     

    Êmili.

     

     

    terça-feira, 26 de julho de 2011 20:17