none
Select com Subquery RRS feed

  • Pergunta

  • Bom dia,

    Gostaria da ajuda de vocês.

    Estou tentando fazer uma query que em tese é similar a de baixo, mas está retornando um erro.

    select top (10) xprod, xcli, lucro_final
    from vRelatorios_Analises_Margem as a left outer join emitente e on (a.cemp=e.cod_empresa)
    where xmarca like '3B RIO' and data between '20110113' and '20110713'
    order by (select distinct xprod from vrelatorios_analises_margem)

     

    Tentando explicar melhor a query:

    Quero selecionar apenas os 10 primeiros valores onde é ordenado pelo distinct de outra consulta.

    Resumindo, eu tenho uma tabela mais ou menos assim:

    xprod

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Importador Importador Marcha

    Tunel Traseiro Preto

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 2 Pecas

     

    Enfim, na consulta eu quero selecionar todos os valores de todas as colunas (até as que não coloquei aqui porque não se faz necessário), porém no top (10) tem que vim os 10 primeiros valores do distinct. Por exemplo: Se eu quisesse selecionar só essa coluna xprod e colocass select xprod from table1, viria todos os valores acima listados, se eu colocasse distinct não se repetiria os valores, logo um top10 me mostraria os 10 primeiros valores distintos, porém eu só preciso desse distinct no order by. Pra poder pegar todos os 10 valores distintos eu fiz da forma que coloquei acima, porém dá o seguinte erro:

    Msg 512, Level 16, State 1, Line 1
    Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

    Se alguém souber de uma solução, fico no aguardo.


    Rodrigo Ataíde.
    segunda-feira, 16 de janeiro de 2012 13:49

Respostas

  • Rodrigo,

    pelo que eu entendi você está querendo na primeira parte do seu resultado os registros com o distinct e logo após todos os demais regustros. É isso?

    Caso seja, acho que este vai te atender. Fiz o exemplo baseado no post do Weslley.

    drop table #teste
    go
    create table #teste (id int identity(1,1) primary key, xprod varchar(100))
    go
    
    insert into #teste values 
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Importador Importador Marcha'),
    ('Tunel Traseiro Preto'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 2 Pecas')
    
    
    ;With cteProd As (
                      select   id,
                               xprod,
                               row_number()over(partition by xprod order by id asc) as seq
                      from     #teste
    )
    -- Identifica os registros diferentes
    Select   1 Grupo, xprod
    From     cteProd
    where    seq = 1
    Union All
    -- Retorna todos os restantes
    Select   2, xprod
    From     cteProd
    where    seq <> 1
    -- Ordena os dados pelo grupo (onde 1 retorna os dados distintos e 2 retorna todos os outros registros) e pelo produto
    Order by Grupo, xprod
    

     


    Espero que ajude! Luiz Phellipe
    • Marcado como Resposta Rodrigo Ataíde quarta-feira, 18 de janeiro de 2012 11:25
    terça-feira, 17 de janeiro de 2012 23:15

Todas as Respostas

  • Rodrigo,

        Tente assim:

    select top (10) xprod, xcli, lucro_final
    from vRelatorios_Analises_Margem as a left outer join emitente e on (a.cemp=e.cod_empresa)
    where xmarca like '3B RIO' and data between '20110113' and '20110713'
    order by xprod


    Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008
    segunda-feira, 16 de janeiro de 2012 13:57
    Moderador
  • Olá Roberto,

    Se eu tentar assim, ele vai  trazer os 10 primeiros valores de Tapete Piso Preto 4 Pecas.

    Eu gostaria de trouxesse ordenado pelo distinct do xprod, assim dessa forma, no top 10 viria todos os xprod.

    Entendeu?


    Rodrigo Ataíde.
    segunda-feira, 16 de janeiro de 2012 14:00
  • Se colocar  assim

     

    select Distinct top (10) xprod, xcli, lucro_final
    from vRelatorios_Analises_Margem as a left outer join emitente e on (a.cemp=e.cod_empresa)
    where xmarca like '3B RIO' and data between '20110113' and '20110713'
    order by xprod

    Não consegue o que você precisa?

    O que ele lhe retorna?

    Se não coloca um Distinct separado

    Select Distinct * from (select Distinct top (10) xprod, xcli, lucro_final
    from vRelatorios_Analises_Margem as a left outer join emitente e on (a.cemp=e.cod_empresa)
    where xmarca like '3B RIO' and data between '20110113' and '20110713'
    order by xprod) as x

     

    segunda-feira, 16 de janeiro de 2012 19:45
  • Olá Luiz Felipe,

    A primeira query que você colocou gera erro, pois não tem como distinguir mais de uma coluna, se eu colocasse só select distinct top (10) xprod from .... Funcionaria, mas quando eu coloco mais de uma coluna, o distinct não funciona.

    A segunda query tem erro de sintaxe, pois no primeiro from eu to pegando uma tabela de um select. Não faz sentido. Entendeu?


    Rodrigo Ataíde.
    segunda-feira, 16 de janeiro de 2012 19:57
  • Rodrigo, consegue colocar um script com as tabelas e os dados existentes nelas, e o resultado que você deseja ?

    Dai fica mais fácil de visualizarmos/testar o que você quer.

     

    Abs.


    Fabiano Neves Amorim - SQL Server MVP http://blogs.solidq.com/fabianosqlserver/
    terça-feira, 17 de janeiro de 2012 14:29
  • Também não consegui entender...
    Abraços, Weslley Moura MCP - MCTS - ORA SqlExpert
    terça-feira, 17 de janeiro de 2012 16:00
  • Olá,

    Como informei, eu possuo aquela estrutura citada no primeiro post.

    Eu preciso de um select que ordene pelas informações citadas acima, porém distinguindo cada informação.

    ou seja, a estrutura é essa, onde xprod é o nome da coluna:

    xprod

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Importador Importador Marcha

    Tunel Traseiro Preto

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 2 Pecas

     

    Eu preciso de um select que me retorne da seguinte maneira:

    xprod

    Tapete Piso Preto 4 Pecas

    Importador Importador Marcha

    Tunel Traseiro Preto

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 2 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 Pecas

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

    Tapete Piso Preto 4 PCS

     

    Entenderam?


    Rodrigo Ataíde.
    terça-feira, 17 de janeiro de 2012 17:04
  • Veja se é isso:

    drop table #teste
    go
    create table #teste (id int identity(1,1) primary key, xprod varchar(100))
    go

    insert into #teste values
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Importador Importador Marcha'),
    ('Tunel Traseiro Preto'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 2 Pecas')


    select    *
    from    (
            select    id,
                    xprod,
                    row_number()over(partition by xprod order by id asc) as seq
            from    #teste
            ) a
    where    seq = 1
    order by id


    Abraços, Weslley Moura MCP - MCTS - ORA SqlExpert
    terça-feira, 17 de janeiro de 2012 19:15
  • Olá Weslley,

    Testei aqui e seria dessa forma. Porém cadê o resto das informações. Entendeu?

    De 18 dados, só aparecem 5. Eu gostaria que aparecesse os 18, porém que fosse order by igual a sua solução, e abaixo o restante.


    Rodrigo Ataíde.
    terça-feira, 17 de janeiro de 2012 19:33
  • Rodrigo,

    pelo que eu entendi você está querendo na primeira parte do seu resultado os registros com o distinct e logo após todos os demais regustros. É isso?

    Caso seja, acho que este vai te atender. Fiz o exemplo baseado no post do Weslley.

    drop table #teste
    go
    create table #teste (id int identity(1,1) primary key, xprod varchar(100))
    go
    
    insert into #teste values 
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Tapete Piso Preto 4 Pecas'),
    ('Importador Importador Marcha'),
    ('Tunel Traseiro Preto'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 4 PCS'),
    ('Tapete Piso Preto 2 Pecas')
    
    
    ;With cteProd As (
                      select   id,
                               xprod,
                               row_number()over(partition by xprod order by id asc) as seq
                      from     #teste
    )
    -- Identifica os registros diferentes
    Select   1 Grupo, xprod
    From     cteProd
    where    seq = 1
    Union All
    -- Retorna todos os restantes
    Select   2, xprod
    From     cteProd
    where    seq <> 1
    -- Ordena os dados pelo grupo (onde 1 retorna os dados distintos e 2 retorna todos os outros registros) e pelo produto
    Order by Grupo, xprod
    

     


    Espero que ajude! Luiz Phellipe
    • Marcado como Resposta Rodrigo Ataíde quarta-feira, 18 de janeiro de 2012 11:25
    terça-feira, 17 de janeiro de 2012 23:15
  • Excelente Luiz Phellipe!
    Abraços, Weslley Moura MCP - MCTS - ORA SqlExpert
    quarta-feira, 18 de janeiro de 2012 11:32