none
Selecioanr os x primeiros de cada tipo RRS feed

  • Pergunta

  • Olá pessoal,
    estou iniciando maeus estudos sobre SQL e deparei com uma dúvida. Perguntei para alguns amigos mas não tive uma resposta satisfatória. Então recorri ao fórum.

    Tenho uma tabela assim:
    id_artigo | tipo | titulo

    na coluna tipo eu tenho os possiveis valores: Artigos, Clipping, Review e Noticias.

    Considerando que eu tenho mais de 100 registros pra cada um desses tipos
    Gostaria de fazer um select que me retornasse apenas os 5 primeiros de cada tipo ordenados pelo tipo.

    Atualmente faço assim:


    Code Snippet

    SELECT id_artigo, tipo, titulo FROM artigos
    WHERE id_artigo IN (
        SELECT Top 2 id_artigo
        FROM artigos
        WHERE tipo = 'Artigos'
        ORDER BY tipo
    ) OR id_artigo IN (
        SELECT Top 2 id_artigo
        FROM artigos
        WHERE tipo = 'Clipping'
        ORDER BY tipo
    ) ORDER BY tipo


    Como podem ver, com a minha soluçao eu precisaria criar um OR pra cada valor, teria como automatizar isso? pra caso eu recebar valores diferente dos que tenho hoje.

    Abraço e agradeço a atenção desde já.

    sexta-feira, 15 de fevereiro de 2008 18:26

Respostas

  • Olá Felipe,

     

    No caso do SQL Server 2005, teríamos de utilizar as extensões proprietárias do Transact SQL. Faz algum tempo que não leio a fundo o padrão ANSI (infelizmente ele é pago). Algumas revisões foram realizadas (acho que 2003 ou 2006) foi a última com bastante foco em XML. Não sei se o padrão prevê algum operador do tipo. No SQL Server 2005, ficaria da seguinte forma:

     

    Code Snippet

    CREATE TABLE #tblClientes (CodigoCliente INT, Nome VARCHAR(20))

     

    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (1,'Cliente 1')
    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (2,'Cliente 2')
    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (3,'Cliente 3')
    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (4,'Cliente 4')

     

    CREATE TABLE #tblVendas (
     CodigoVendas INT Identity(1,1),
     CodigoCliente INT, Valor DECIMAL(10,2))

     

    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (1,1200)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (2,1000)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (3,1300)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (1,1500)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (2,1900)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (3,1500)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (1,1100)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (2,1000)

     

    -- Recuperar as duas primeiras vendas de cada cliente

    SELECT * FROM #tblClientes
    CROSS APPLY (SELECT TOP 2 * FROM #tblVendas
     WHERE CodigoCliente = #tblClientes.CodigoCliente) AS Res

     

    -- Recuperar as duas primeiras vendas de cada cliente (mesmo os que não fizeram vendas)

    SELECT * FROM #tblClientes
    OUTER APPLY (SELECT TOP 2 * FROM #tblVendas
     WHERE CodigoCliente = #tblClientes.CodigoCliente) AS Res

     

    DROP TABLE #tblVendas

    DROP TABLE #tblClientes

     

     

     

    [ ]s,

     

    Gustavo

    terça-feira, 19 de fevereiro de 2008 12:00

Todas as Respostas

  • Boa Tarde Felipe,

     

    Seja bem vindo ao fórum. Tentaremos tirar as suas dúvidas e ajudá-lo a resolver os seus problemas. Infelizmente no SQL Server 2000 estamos limitados, mas se você estiver usando o SQL Server 2005 há outras construções apropriadas para esse tipo de situação.

     

    [ ]s,

     

    Gustavo

     

    sexta-feira, 15 de fevereiro de 2008 18:38
  • Gustavo,

    obrigado pelas boas vindas.

    uso o 2000 mesmo, mas no caso do sql server 2005, essas instruções estariam de acordo com SQL ANSI ou seria um artifício que só funcionaria nele?

     

    Abraço.

    terça-feira, 19 de fevereiro de 2008 11:42
  • Olá Felipe,

     

    No caso do SQL Server 2005, teríamos de utilizar as extensões proprietárias do Transact SQL. Faz algum tempo que não leio a fundo o padrão ANSI (infelizmente ele é pago). Algumas revisões foram realizadas (acho que 2003 ou 2006) foi a última com bastante foco em XML. Não sei se o padrão prevê algum operador do tipo. No SQL Server 2005, ficaria da seguinte forma:

     

    Code Snippet

    CREATE TABLE #tblClientes (CodigoCliente INT, Nome VARCHAR(20))

     

    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (1,'Cliente 1')
    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (2,'Cliente 2')
    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (3,'Cliente 3')
    INSERT INTO #tblClientes (CodigoCliente, Nome) VALUES (4,'Cliente 4')

     

    CREATE TABLE #tblVendas (
     CodigoVendas INT Identity(1,1),
     CodigoCliente INT, Valor DECIMAL(10,2))

     

    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (1,1200)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (2,1000)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (3,1300)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (1,1500)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (2,1900)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (3,1500)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (1,1100)
    INSERT INTO #tblVendas (CodigoCliente, Valor) VALUES (2,1000)

     

    -- Recuperar as duas primeiras vendas de cada cliente

    SELECT * FROM #tblClientes
    CROSS APPLY (SELECT TOP 2 * FROM #tblVendas
     WHERE CodigoCliente = #tblClientes.CodigoCliente) AS Res

     

    -- Recuperar as duas primeiras vendas de cada cliente (mesmo os que não fizeram vendas)

    SELECT * FROM #tblClientes
    OUTER APPLY (SELECT TOP 2 * FROM #tblVendas
     WHERE CodigoCliente = #tblClientes.CodigoCliente) AS Res

     

    DROP TABLE #tblVendas

    DROP TABLE #tblClientes

     

     

     

    [ ]s,

     

    Gustavo

    terça-feira, 19 de fevereiro de 2008 12:00
  •  

    Gustavo,

    muito obrigado pela sua atenção.

    Vlw mesmo.

     

    Abraço!

    terça-feira, 19 de fevereiro de 2008 12:09