none
UNION ALL com ORDER BY RRS feed

  • Pergunta

  • Boa tarde pessoal,

    Tenho 2 selects

    SELECT DISTINCT TOP 40
    NomePF
    , Classificacao
    , RelevanciaSitMercado
    , Idade
    , Escolaridade
    , RelevanciaPosFamilia
    , RendaPerCapita
    FROM TESTE
    WHERE Sexo = 'F'

    UNION ALL
    SELECT DISTINCT TOP 110
    NomePF
    , Classificacao
    , RelevanciaSitMercado
    , Idade
    , Escolaridade
    , RelevanciaPosFamilia
    , RendaPerCapita
    FROM TESTE
    WHERE Sexo = 'M'

    ORDER BY Classificacao DESC
    , RelevanciaSitMercado
    , Idade DESC
    , RelevanciaPosFamilia
    , RendaPerCapita


    O meu problema é que ele está ordenando apenas o segundo SELECT.
    O que tem de errado?

    Obrigada

    segunda-feira, 14 de maio de 2012 19:02

Respostas

  • Bom dia Fernanda,

    Claro. Vou direto para a parte que interessa.

    É necessário ordenar cada uma de suas sub-queries individualmente e após uni-las ainda é necessário ordenar o result set como um todo. Para evitar três GROUP BY's repetidos, achei melhor utilizar CTEs combinadas com Ranking Functions. O código está comentado:

    WITH
    /* Esta CTE criará um número de ranking de acordo com a ordenação desejada por você */
    Ordenacao AS
    (
    	SELECT *, RANK() OVER(ORDER BY Classificacao DESC, RelevanciaSitMercado, Idade DESC, RelevanciaPosFamilia, RendaPerCapita) AS OrdemGeral
    	FROM TESTE
    ),
    /* Então esta CTE criará um número de ranking para cada sexo, permitindo que você restrinja a quantidade de registros por sexo */
    Pessoas AS
    (
    	SELECT *, RANK() OVER(PARTITION BY Sexo ORDER BY OrdemGeral) AS OrdemSexo
    	FROM Ordenacao
    )
    /* Aqui os registros são selecionados */
    SELECT NomePF, Classificacao, RelevanciaSitMercado, Idade, Escolaridade, RelevanciaPosFamilia, RendaPerCapita
    FROM Pessoas
    /* Aqui restringidos a 40 mulheres e 110 homens */
    WHERE (Sexo = 'F' AND OrdemSexo <= 40) OR (Sexo = 'M' AND OrdemSexo <= 110)
    /* E por fim, ordenado pela condição de ordenação inicial */
    ORDER BY OrdemGeral;

    Caso tenha alguma dúvida ou seu problema persista, estou disposto a lhe ajudar até que o mesmo seja solucionado!

    []'s


    MCP | MCTS SQL Server 2008 Database Developer

    terça-feira, 15 de maio de 2012 12:41

Todas as Respostas

  • Olá Fernanda,

    Acredito que isto esta ocorrendo por causa do top

    tente desta forma

    SELECT * FROM (SELECT DISTINCT TOP 40 NomePF , Classificacao , RelevanciaSitMercado , Idade , Escolaridade , RelevanciaPosFamilia , RendaPerCapita FROM TESTE WHERE Sexo = 'F'

    ORDER BY Classificacao DESC
    , RelevanciaSitMercado
    , Idade DESC
    , RelevanciaPosFamilia
    , RendaPerCapita) A UNION ALL

    SELECT * FROM

    ( SELECT DISTINCT TOP 110 NomePF , Classificacao , RelevanciaSitMercado , Idade , Escolaridade , RelevanciaPosFamilia , RendaPerCapita FROM TESTE WHERE Sexo = 'M'

    ORDER BY Classificacao DESC
    , RelevanciaSitMercado
    , Idade DESC
    , RelevanciaPosFamilia
    , RendaPerCapita) B



    Att.
    Lukas Baldan


    segunda-feira, 14 de maio de 2012 19:08
  • Oi Lukas, obrigada pelo retorno, mas eu fiz do jeitinho que vc falou e não alterou em nada o resultado. =(

    Obrigada!

    segunda-feira, 14 de maio de 2012 19:15
  • Desculpe estava errado mesmo

    tente desta forma

     SELECT * FROM 
    (SELECT DISTINCT TOP 40
     NomePF
     , Classificacao
     , RelevanciaSitMercado
     , Idade
     , Escolaridade
     , RelevanciaPosFamilia
     , RendaPerCapita
     FROM TESTE
     WHERE Sexo = 'F'
    ORDER BY Classificacao DESC , RelevanciaSitMercado , Idade DESC , RelevanciaPosFamilia , RendaPerCapita) A 
    UNION ALL
    SELECT * FROM ( SELECT DISTINCT TOP 110
     NomePF
     , Classificacao
     , RelevanciaSitMercado
     , Idade
     , Escolaridade
     , RelevanciaPosFamilia
     , RendaPerCapita
     FROM TESTE
     WHERE Sexo = 'M'ORDER BY Classificacao DESC , RelevanciaSitMercado , Idade DESC , RelevanciaPosFamilia , RendaPerCapita) B


    Att.
    Lukas Baldan


    segunda-feira, 14 de maio de 2012 19:19
  • Lukas, o seu select não ordenará corretamente pois você utilizou dois ORDER BY's, um para ordernar as pessoas do sexo feminino e outro para ordenar as do sexo masculino. Isto é, os dois result sets são ordenados individualmente e em seguida são unidos.

    Acredito que a ideia da Fernanda seja ordernar os registros como um todo. Assim precisamos unir os dois result sets e somente após isto ordernar os registros.

    ---

    Fernanda, veja se esta solução atende o seu problema:

    SELECT * FROM
    	(
    		SELECT DISTINCT TOP 40
    		NomePF
    		, Classificacao
    		, RelevanciaSitMercado
    		, Idade
    		, Escolaridade
    		, RelevanciaPosFamilia
    		, RendaPerCapita
    		FROM TESTE
    		WHERE Sexo = 'F'
    		UNION ALL
    		SELECT DISTINCT TOP 110
    		NomePF
    		, Classificacao
    		, RelevanciaSitMercado
    		, Idade
    		, Escolaridade
    		, RelevanciaPosFamilia
    		, RendaPerCapita
    		FROM TESTE
    		WHERE Sexo = 'M'
    	) AS tb
    ORDER BY Classificacao DESC
    	, RelevanciaSitMercado
    	, Idade DESC
    	, RelevanciaPosFamilia
    	, RendaPerCapita

    Espero ter ajudado.

    []'s


    MCP | MCTS SQL Server 2008 Database Developer




    segunda-feira, 14 de maio de 2012 19:22
  • Obrigada pelas duas respostas mas não deram certo, a do Lukas realmente separa as pessoas (Masculino e Feminino), já a do Filipe tem o mesmo comportamento de quando como eu estava fazendo antes.

    Obrigada!

    segunda-feira, 14 de maio de 2012 20:03
  • Fernanda,

    acredito que entendi errado, eu achei que você queria ordenar antes de obter os top de cada select,

    acredito que as querys estão certas, tem como você explicar melhor o que você quer, fornecer alguns exemplos de como os dados estão na tabela e como voce espera o select final??


    Att.
    Lukas Baldan

    segunda-feira, 14 de maio de 2012 20:11
  • Desculpa pessoal, talvez esteja me expressando de forma incorreta.

    Segue modelo de retorno correto:

    NomePF Classificacao RelevanciaSitMercado Idade Escolaridade RelevanciaPosFamilia RendaPerCapita Sexo
    neusa lopes da cunha 1 1 49 40 3 0.00

    F

    Denilson Cerqueira dos Santos 1 1 44 40 3 0.00

    M

    CLAUDIO DA SILVA BARROS 1 2 53 40 2 0.00

    M

    maria de fatima santos 1 2 45 40 3 0.00 F
    segunda-feira, 14 de maio de 2012 20:18
  • Fernanda,

    Acho que entendi o seu problema.

    Digamos que o seu select retorne "as pessoas com melhor classificação", apenas para exemplificar. Você precisa selecionar as 40 mulheres melhores qualificadas mais os 110 homens melhores qualificados, e então ordenar todas estas 150 pessoas de acordo com suas classificações, certo?

    Se usarmos as forma que o Lukas sugeriu, irá buscar as 40 mulheres mais qualificadas mais os 110 homens mais qualificados, mas não organizará todas as 150 pessoas por classificação. Da forma que eu havia sugerido, é feito o contrário: são selecionadas 40 quaisquer mulheres mais 110 quaisquer homens, e então este subconjunto é classificado.

    ===

    Para resolver o seu problema, é necessário ordenar as 40 mulheres individualmente, os 110 homens individualmente, e por fim as 150 pessoas como um todo. Mais ou menos como juntar as soluções propostas pelo Lukas e por mim. Mas isto repetiria muito as ordenações, tornando a query de árdua manutenção.

    Para não repetirmos a mesma ordenação três vezes, sugiro utilizarmos CTEs combinadas com Ranking Functions. Veja se isto lhe atende:

    WITH
    /* Esta CTE criará um número de ranking de acordo com a ordenação desejada por você */
    Ordenacao AS
    (
    	SELECT *, RANK() OVER(ORDER BY Classificacao DESC, RelevanciaSitMercado, Idade DESC, RelevanciaPosFamilia, RendaPerCapita) AS OrdemGeral
    	FROM TESTE
    ),
    /* Então esta CTE criará um número de ranking para cada sexo, permitindo que você restrinja a quantidade de registros por sexo */
    Pessoas AS
    (
    	SELECT *, RANK() OVER(PARTITION BY Sexo ORDER BY OrdemGeral) AS OrdemSexo
    	FROM Ordenacao
    )
    /* Aqui os registros são selecionados */
    SELECT NomePF, Classificacao, RelevanciaSitMercado, Idade, Escolaridade, RelevanciaPosFamilia, RendaPerCapita
    FROM Pessoas
    /* Aqui restringidos a 40 mulheres e 110 homens */
    WHERE (Sexo = 'F' AND OrdemSexo <= 40) OR (Sexo = 'M' AND OrdemSexo <= 110)
    /* E por fim, ordenado pela condição de ordenação inicial */
    ORDER BY OrdemGeral;

    []'s


    MCP | MCTS SQL Server 2008 Database Developer

    segunda-feira, 14 de maio de 2012 20:36
  • Bom dia Filipe.

    Não consegui visualizar a resposta inteira, vc poderia postá-la novamente por favor.

    Muito obrigada =)

    terça-feira, 15 de maio de 2012 11:37
  • Bom dia Fernanda,

    Claro. Vou direto para a parte que interessa.

    É necessário ordenar cada uma de suas sub-queries individualmente e após uni-las ainda é necessário ordenar o result set como um todo. Para evitar três GROUP BY's repetidos, achei melhor utilizar CTEs combinadas com Ranking Functions. O código está comentado:

    WITH
    /* Esta CTE criará um número de ranking de acordo com a ordenação desejada por você */
    Ordenacao AS
    (
    	SELECT *, RANK() OVER(ORDER BY Classificacao DESC, RelevanciaSitMercado, Idade DESC, RelevanciaPosFamilia, RendaPerCapita) AS OrdemGeral
    	FROM TESTE
    ),
    /* Então esta CTE criará um número de ranking para cada sexo, permitindo que você restrinja a quantidade de registros por sexo */
    Pessoas AS
    (
    	SELECT *, RANK() OVER(PARTITION BY Sexo ORDER BY OrdemGeral) AS OrdemSexo
    	FROM Ordenacao
    )
    /* Aqui os registros são selecionados */
    SELECT NomePF, Classificacao, RelevanciaSitMercado, Idade, Escolaridade, RelevanciaPosFamilia, RendaPerCapita
    FROM Pessoas
    /* Aqui restringidos a 40 mulheres e 110 homens */
    WHERE (Sexo = 'F' AND OrdemSexo <= 40) OR (Sexo = 'M' AND OrdemSexo <= 110)
    /* E por fim, ordenado pela condição de ordenação inicial */
    ORDER BY OrdemGeral;

    Caso tenha alguma dúvida ou seu problema persista, estou disposto a lhe ajudar até que o mesmo seja solucionado!

    []'s


    MCP | MCTS SQL Server 2008 Database Developer

    terça-feira, 15 de maio de 2012 12:41
  • Oi Filipe, tem alguma coisa escrita depois do comentário: /* E por fim, ordenado pela condição de ordenação inicial */ ?

    Obrigada.

    terça-feira, 15 de maio de 2012 13:03
  • No código do felipe,

    tem a linha

    ORDER BY OrdemGeral; 



    Att.
    Lukas Baldan


    terça-feira, 15 de maio de 2012 13:08
  • Que estranho estar cortando o código aí.. não tem nenhum link "ver mais", "ler mais" na mensagem?

    Mas enfim, é isso mesmo que o Lukas apontou.

    Obrigado Lukas. :)


    MCP | MCTS SQL Server 2008 Database Developer

    terça-feira, 15 de maio de 2012 13:16
  • Felipe, tambem achei estranho...

    nunca vi cortar o código.

    []´s


    Att.
    Lukas Baldan


    terça-feira, 15 de maio de 2012 13:18
  • É, tava cortando... Também achei estranho.

    Muito obrigada, a solução deu certo e ficou rápida também.

    Obrigada. =)

    terça-feira, 15 de maio de 2012 13:44
  • Acho até injusto marcar somente uma resposta como válida uma vez que as duas me ajudaram muito.

    Se pudesse marcar as duas como resposta, com certeza marcaria.

    terça-feira, 15 de maio de 2012 13:45