none
Como saber o menor valor de um registro com 5 colunas por exemplo RRS feed

  • Pergunta

  •  

    Opa pessoal, alguem poderia me dizer como que eu posso descobrir o menor valor de uma tabela com 5 colunas , e 1 registro? O tipo do campo é decimal. Desde já agradeço!
    domingo, 20 de abril de 2008 13:16

Respostas

  • segue exemplo

     

     

     Create Table #Exemplo (campo1 int, campo2 int, campo3 int, campo4 int , campo5 int)

     insert into #Exemplo (campo1, campo2, campo3, campo4, campo5) Values (34,89,00,34,12)


     Select min (campo) From
     (
     Select campo1 As Campo
     From #Exemplo
     union all
     Select campo2
     From #Exemplo
     union all
     Select campo3
     From #Exemplo
     union all
     Select campo4
     From #Exemplo
     union all
     Select campo5
     From #Exemplo
     ) Drv

     

     

     

    mais vc. pode criar uma funcao em que vc. passe uma string com valor separado por , dai retorna o menor valor.

     

    CREATE  Function Ufn_TableArray (@VarArray Varchar(8000))
    Returns @TableArray Table (Item varchar(50)) AS
    BEGIN
       
         If @VarArray Is null
             INSERT INTO @TableArray (Item) VALUES (Null) 
        
         Declare @Indice      AS TinyInt
         Declare @IndiceArray AS TinyInt
         Declare @VarAcum     AS nvarchar(10)

         SET @VarArray = @VarArray + ','
         SET @VarAcum = ''
         SET @Indice = 1
         SET @IndiceArray = 0

         WHILE @Indice <= Len(@VarArray)
         BEGIN
      IF Substring(@VarArray,@Indice,1) = ','
      BEGIN
          INSERT INTO @TableArray (Item) VALUES (@VarAcum)
                 SET @VarAcum = ''
        END
      ELSE
      BEGIN
          SET @VarAcum = rtrim(Convert(char(10),@VarAcum)) + rtrim(convert(char(10),Substring(@VarArray,@Indice,1)))
      END
      SET @Indice = @Indice+1
         END

    RETURN
    END


    Declare @String As Varchar(1000)
     
       Select @String = convert(varchar(10),campo1) + ',' +
              convert(varchar(10),campo2) + ',' +
       convert(varchar(10),campo3) + ',' +
       convert(varchar(10),campo4) + ',' +
              convert(varchar(10),campo5) From #Exemplo

    Select Min(Item) From dbo.Ufn_TableArray(@String)

     

    Abs;

     

    terça-feira, 22 de abril de 2008 10:52

Todas as Respostas

  •  

    Alguma ideia galera??
    terça-feira, 22 de abril de 2008 10:47
  • segue exemplo

     

     

     Create Table #Exemplo (campo1 int, campo2 int, campo3 int, campo4 int , campo5 int)

     insert into #Exemplo (campo1, campo2, campo3, campo4, campo5) Values (34,89,00,34,12)


     Select min (campo) From
     (
     Select campo1 As Campo
     From #Exemplo
     union all
     Select campo2
     From #Exemplo
     union all
     Select campo3
     From #Exemplo
     union all
     Select campo4
     From #Exemplo
     union all
     Select campo5
     From #Exemplo
     ) Drv

     

     

     

    mais vc. pode criar uma funcao em que vc. passe uma string com valor separado por , dai retorna o menor valor.

     

    CREATE  Function Ufn_TableArray (@VarArray Varchar(8000))
    Returns @TableArray Table (Item varchar(50)) AS
    BEGIN
       
         If @VarArray Is null
             INSERT INTO @TableArray (Item) VALUES (Null) 
        
         Declare @Indice      AS TinyInt
         Declare @IndiceArray AS TinyInt
         Declare @VarAcum     AS nvarchar(10)

         SET @VarArray = @VarArray + ','
         SET @VarAcum = ''
         SET @Indice = 1
         SET @IndiceArray = 0

         WHILE @Indice <= Len(@VarArray)
         BEGIN
      IF Substring(@VarArray,@Indice,1) = ','
      BEGIN
          INSERT INTO @TableArray (Item) VALUES (@VarAcum)
                 SET @VarAcum = ''
        END
      ELSE
      BEGIN
          SET @VarAcum = rtrim(Convert(char(10),@VarAcum)) + rtrim(convert(char(10),Substring(@VarArray,@Indice,1)))
      END
      SET @Indice = @Indice+1
         END

    RETURN
    END


    Declare @String As Varchar(1000)
     
       Select @String = convert(varchar(10),campo1) + ',' +
              convert(varchar(10),campo2) + ',' +
       convert(varchar(10),campo3) + ',' +
       convert(varchar(10),campo4) + ',' +
              convert(varchar(10),campo5) From #Exemplo

    Select Min(Item) From dbo.Ufn_TableArray(@String)

     

    Abs;

     

    terça-feira, 22 de abril de 2008 10:52
  • Marcelo,

     

    Concordo com você em relação a utilizar uma função, fica mais fácil e prático.

     

    Outra possibilidade, seria obter o menor valor de cada coluna e armazenar dentro de uma outra table, e depois obter o menor valor deste novo conjunto de valores.

    terça-feira, 22 de abril de 2008 11:18
  •  Junior Galvão - MVP wrote:

    Marcelo,

     

    Concordo com você em relação a utilizar uma função, fica mais fácil e prático.

     

    Outra possibilidade, seria obter o menor valor de cada coluna e armazenar dentro de uma outra table, e depois obter o menor valor deste novo conjunto de valores.

     

    Junior e Marcelo,

    Obrigado pelas respostas. Eu estava tentando fazer utilizando uma função com uma tabela temporaria, mas encontrei alguns erros e desisti... Vlw!

    terça-feira, 22 de abril de 2008 14:36
  • Bom Dia,

     

    Segue a primeira sugestão

     

    Code Snippet

    CREATE TABLE #tbl (

    COL1 INT,

    COL2 INT,

    COL3 INT,

    COL4 INT,

    COL5 INT)

     

    INSERT INTO #tbl VALUES (3,2,5,6,4)

    DECLARE

    @COL1 INT,

    @COL2 INT,

    @COL3 INT,

    @COL4 INT,

    @COL5 INT,

    @RES INT

     

    SELECT

    @COL1 = COL1, @COL2 = COL2, @COL3 = COL3, @COL4 = COL4, @COL5 = COL5

    FROM

    #tbl

     

    SET @RES = @COL1

    IF @COL1 > @COL2

    SET @RES = @COL2

    IF @RES > @COL3

    SET @RES = @COL3

    IF @RES > @COL4

    SET @RES = @COL4

    IF @RES > @COL5

    SET @RES = @COL5

     

    SELECT @RES AS MENOR

     

    DROP TABLE #tbl

     

     

    Como sou adepto de soluções mais simples, se você tiver o SQL Server 2005 use o seguinte código (para o meu exemplo)

     

    Code Snippet

    WITH Consulta AS (

    SELECT *

    FROM

    (SELECT Col1, Col2, Col3, Col4, Col5

    FROM #tbl) t1

    UNPIVOT

    (Valor FOR Coluna IN

    (Col1, Col2, Col3, Col4, Col5)

    )AS t2)

     

    SELECT TOP 1 * FROM Consulta

    ORDER BY Valor ASC

     

     

    Essa solução é mais adequada para situações onde não se tem apenas um registro.

     

    [ ]s,

     

    Gustavo

    terça-feira, 22 de abril de 2008 14:50
  •  Gustavo Maia Aguiar wrote:

    Bom Dia,

     

    Segue a primeira sugestão

     

    Code Snippet

    CREATE TABLE #tbl (

    COL1 INT,

    COL2 INT,

    COL3 INT,

    COL4 INT,

    COL5 INT)

     

    INSERT INTO #tbl VALUES (3,2,5,6,4)

    DECLARE

    @COL1 INT,

    @COL2 INT,

    @COL3 INT,

    @COL4 INT,

    @COL5 INT,

    @RES INT

     

    SELECT

    @COL1 = COL1, @COL2 = COL2, @COL3 = COL3, @COL4 = COL4, @COL5 = COL5

    FROM

    #tbl

     

    SET @RES = @COL1

    IF @COL1 > @COL2

    SET @RES = @COL2

    IF @RES > @COL3

    SET @RES = @COL3

    IF @RES > @COL4

    SET @RES = @COL4

    IF @RES > @COL5

    SET @RES = @COL5

     

    SELECT @RES AS MENOR

     

    DROP TABLE #tbl

     

     

    Como sou adepto de soluções mais simples, se você tiver o SQL Server 2005 use o seguinte código (para o meu exemplo)

     

    Code Snippet

    WITH Consulta AS (

    SELECT *

    FROM

    (SELECT Col1, Col2, Col3, Col4, Col5

    FROM #tbl) t1

    UNPIVOT

    (Valor FOR Coluna IN

    (Col1, Col2, Col3, Col4, Col5)

    )AS t2)

     

    SELECT TOP 1 * FROM Consulta

    ORDER BY Valor ASC

     

     

    Essa solução é mais adequada para situações onde não se tem apenas um registro.

     

    [ ]s,

     

    Gustavo

     

    Opa Gustavo, obrigado por suas dicas, são bem legais... Acho q ja tinha dito no post acima, estava inclinado a fazer algo parecido com a sua primeira dica, mas como vc mesmo disse a segunda forma é muito mais pratica! Teria como vc me explicar ela um pouco? Nunca usei estes artificios no sql server 2005. Vlw!

    quarta-feira, 23 de abril de 2008 12:09
  • Olá GJúnior,

     

    O SQL Server dispõe de operadores para transformar linhas em colunas e colunas em linhas (PIVOT e UNPIVOT). Quando utilizamos linhas é fácil achar o menor valor. Basta utilizar a função MIN e tudo está resolvido. No entanto, quando utilizamos colunas, a solução é um pouco mais complicada (mas não impossível).

     

    No meu exemplo, utilizei o operador UNPIVOT para transformar colunas em linhas e assim recuperar o resultado por ordem de valor (ORDER BY Valor). O operador TOP traz apenas o primeiro registro de forma a retornar o menor valor.

     

    As soluções anteriores são interessantes mas além de mais trabalhosas são um pouco menos performáticas para o caso de muitos registros. Se tivéssemos vários registros com várias colunas e quiséssemos saber o menor valor de cada coluna a solução do UNPIVOT seria muito bem vinda (teríamos só que adaptar o TOP para um GROUP BY um pouco mais refinado)

     

    Acho interessante desenvolver soluções que funcionem independente da versão (as anteriores funcionam até no SQL Server 7), mas se sua plataforma já é o 2005 seria um desperdício não aproveitar os novos recursos. São mais ágeis e envolvem menos código.

     

    Você poderá obter maiores detalhes sobre essas funções no Books OnLine.

     

    [ ]s,

     

    Gustavo

    quarta-feira, 23 de abril de 2008 12:54
  •  Gustavo Maia Aguiar wrote:

    Olá GJúnior,

     

    O SQL Server dispõe de operadores para transformar linhas em colunas e colunas em linhas (PIVOT e UNPIVOT). Quando utilizamos linhas é fácil achar o menor valor. Basta utilizar a função MIN e tudo está resolvido. No entanto, quando utilizamos colunas, a solução é um pouco mais complicada (mas não impossível).

     

    No meu exemplo, utilizei o operador UNPIVOT para transformar colunas em linhas e assim recuperar o resultado por ordem de valor (ORDER BY Valor). O operador TOP traz apenas o primeiro registro de forma a retornar o menor valor.

     

    As soluções anteriores são interessantes mas além de mais trabalhosas são um pouco menos performáticas para o caso de muitos registros. Se tivéssemos vários registros com várias colunas e quiséssemos saber o menor valor de cada coluna a solução do UNPIVOT seria muito bem vinda (teríamos só que adaptar o TOP para um GROUP BY um pouco mais refinado)

     

    Acho interessante desenvolver soluções que funcionem independente da versão (as anteriores funcionam até no SQL Server 7), mas se sua plataforma já é o 2005 seria um desperdício não aproveitar os novos recursos. São mais ágeis e envolvem menos código.

     

    Você poderá obter maiores detalhes sobre essas funções no Books OnLine.

     

    [ ]s,

     

    Gustavo

     

    Gustavo estou tentando da forma que vc flw, mas ainda assim da um erro, olha meu codigo:

     

    create procedure usp_BuscarMenorTarifaEstabelecimento(@idEstabelecimento int) as

    CREATE TABLE #tbl (COL1 INT,COL2 INT,COL3 INT,COL4 INT,COL5 INT)

    INSERT INTO #tbl select vlnormal, vlsglNormal, vldblNormal, vltplNormal, vlqdpNormal from tarifas where id = @idestabelecimento

    WITH Consulta AS (

    SELECT * FROM (SELECT Col1, Col2, Col3, Col4, Col5 FROM #tbl) t1

    UNPIVOT

    (Valor FOR Coluna IN (Col1, Col2, Col3, Col4, Col5))AS t2)

    SELECT TOP 1 * FROM Consulta

    ORDER BY Valor ASC

     

     

    Vc poderia me ajudar com o erro? Vlw!

    quinta-feira, 24 de abril de 2008 05:38
  • Olá GJúnior,

     

    Usei a tabela temporária apenas para exemplificação. Não é necessário transferir os dados para ela primeiro. Tente o seguinte:

     

    Code Snippet

    create procedure usp_BuscarMenorTarifaEstabelecimento(@idEstabelecimento int) as

    WITH Consulta AS (

    SELECT *

    FROM

    (select vlnormal, vlsglNormal, vldblNormal, vltplNormal, vlqdpNormal from tarifas where id = @idestabelecimento) t1

    UNPIVOT

    (Valor FOR Coluna IN

    (vlnormal, vlsglNormal, vldblNormal, vltplNormal, vlqdpNormal)

    )AS t2)

     

    SELECT TOP 1 * FROM Consulta

    ORDER BY Valor ASC

     

     

    [ ]s,

     

    Gustavo

     

    quinta-feira, 24 de abril de 2008 13:18
  •  Gustavo Maia Aguiar wrote:

    Olá GJúnior,

     

    Usei a tabela temporária apenas para exemplificação. Não é necessário transferir os dados para ela primeiro. Tente o seguinte:

     

    Code Snippet

    create procedure usp_BuscarMenorTarifaEstabelecimento(@idEstabelecimento int) as

    WITH Consulta AS (

    SELECT *

    FROM

    (select vlnormal, vlsglNormal, vldblNormal, vltplNormal, vlqdpNormal from tarifas where id = @idestabelecimento) t1

    UNPIVOT

    (Valor FOR Coluna IN

    (vlnormal, vlsglNormal, vldblNormal, vltplNormal, vlqdpNormal)

    )AS t2)

     

    SELECT TOP 1 * FROM Consulta

    ORDER BY Valor ASC

     

     

    [ ]s,

     

    Gustavo

     

     

    Gustavo, no meu caso deram os seguintes erros:

    Msg 156, Level 15, State 1, Procedure usp_BuscarMenorTarifaEstabelecimento, Line 2

    Incorrect syntax near the keyword 'WITH'.

    Msg 170, Level 15, State 1, Procedure usp_BuscarMenorTarifaEstabelecimento, Line 4

    Line 4: Incorrect syntax near 'UNPIVOT'.

     

    quinta-feira, 24 de abril de 2008 15:07
  • Olá GJunior,

     

    Seu SQL Server é 2005 ? O banco está no modo de compatibilidade 90 (você pode verificar isso através do SQL Server Management Studio)

     

    [ ]s,

     

    Gustavo

     

    quinta-feira, 24 de abril de 2008 15:11
  •  Gustavo Maia Aguiar wrote:

    Olá GJunior,

     

    Seu SQL Server é 2005 ? O banco está no modo de compatibilidade 90 (você pode verificar isso através do SQL Server Management Studio)

     

    [ ]s,

     

    Gustavo

     

     

    Opa Gustavo, com certeza eh o 2005 ( standard ), mas vendo agora, vi q o banco q peguei para testar esta no modo de compatibilidade sql server 2000. Acho q o erro deve vir dai. Vou criar um banco do zero pra testar, qq coisa volto aqui p comentar!

    quinta-feira, 24 de abril de 2008 16:36
  • vc. pode alterar o nivel de compatibilidade, mais e bom recriar os indices depois para atualizar as estatisticas, e testar para ver se alguma rotina de banco pode parar...

     

    Abs;

     

    quinta-feira, 24 de abril de 2008 16:51
  •  Marcelo Colla - MVP wrote:

    vc. pode alterar o nivel de compatibilidade, mais e bom recriar os indices depois para atualizar as estatisticas, e testar para ver se alguma rotina de banco pode parar...

     

    Abs;

     

     

    Marcelo,

     

    Vlw pelo comentario, mas no meu caso acho que nao da ( ou sera q pode? ) pq o server ta com sql server 2000, o cliente eh 2005, vou testar em casa q eh tudo 2005. Flw.

    GALERA ESSE UNPIVOT PODE SER USADO DENTRO DE UMA FUNCAO, PARA QUE EU POSSA CHAMAR DENTRO DE UMA PROCEDURE? VLW!!!

    quinta-feira, 24 de abril de 2008 19:00
  • Boa Tarde,

     

    As ferramentas do cliente não fazem diferença. Afinal elas apenas mandam requisições para o servidor. Se o servidor for 2000 não será possível utilizar esses operadores já que os mesmos são implementados apenas a partir do 2005. Uma vez que você tiver o banco em 2005 com o nível de compatibilidade 90 é possível colocar os operadores PIVOT e UNPIVOT dentro de uma procedure ou function

     

    [ ]s,

     

    Gustavo

     

    • Sugerido como Resposta Michael.loiro sexta-feira, 26 de fevereiro de 2010 18:02
    sábado, 26 de abril de 2008 18:17
  • Tenta isso ai.... SELECT Max(GREATEST(campo1, campo2, campo3, campo4, campo5)) FROM exemplo; Abraços, MICHAEL
    sexta-feira, 26 de fevereiro de 2010 19:26