Usuário com melhor resposta
UNION ALL com ORDER BY

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
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
- Marcado como Resposta Fernanda Giannetti terça-feira, 15 de maio de 2012 13:44
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 ALLSELECT * 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- Editado Lukas de Castro Ruocco Baldan segunda-feira, 14 de maio de 2012 19:17
-
-
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- Editado Lukas de Castro Ruocco Baldan segunda-feira, 14 de maio de 2012 19:20
-
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
- Sugerido como Resposta Filipe M. Oliveira segunda-feira, 14 de maio de 2012 19:24
- Editado Filipe M. Oliveira segunda-feira, 14 de maio de 2012 19:26
- Não Sugerido como Resposta Filipe M. Oliveira segunda-feira, 14 de maio de 2012 20:08
-
-
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 -
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 -
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
- Editado Filipe M. Oliveira segunda-feira, 14 de maio de 2012 20:46
-
-
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
- Marcado como Resposta Fernanda Giannetti terça-feira, 15 de maio de 2012 13:44
-
-
No código do felipe,
tem a linha
ORDER BY OrdemGeral;
Att.
Lukas Baldan
- Editado Lukas de Castro Ruocco Baldan terça-feira, 15 de maio de 2012 13:09
-
-
Felipe, tambem achei estranho...
nunca vi cortar o código.
[]´s
Att.
Lukas Baldan- Editado Lukas de Castro Ruocco Baldan terça-feira, 15 de maio de 2012 13:19
-
-