Como encomendar com union no SQL?


201

É possível solicitar quando os dados são provenientes de muitos selecionar e uni-los? Tal como

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"

Como posso solicitar esta consulta pelo nome.

Alguns disseram que você pode consultar assim.

Select id,name,age
From Student
Where age < 15 or name like "%a%"
Order by name

Mas, neste caso, simplesmente ignoro essa solução.


1
Se você tiver a mesma coluna na consulta de união, no final, coloque a ordem pelo nome da coluna.
Anirban karak

Respostas:


266

Apenas escreva

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"
Order by name

a ordem de é aplicada ao conjunto de resultados completo


45
E se eu quiser que o tipo seja aplicado apenas no topo da UNIÃO?
Marifrahman

7
@marifrahman ver minha resposta stackoverflow.com/a/43855496/2340825
BA TabNabber

2
@marifrahman desculpe por cavar um tópico antigo, mas isso pode ajudar outras pessoas. Caso você queira que o ORDER BY seja aplicado na primeira parte do UNION, proteja esse SELECT entre parênteses.
Lideln Kyoku

82
Select id,name,age
from
(
   Select id,name,age
   From Student
   Where age < 15
  Union
   Select id,name,age
   From Student
   Where Name like "%a%"
) results
order by name

46
Como bernd_k apontou, por definição, os SELECTs individuais que compõem uma UNION não podem conter uma cláusula ORDER BY. A única cláusula ORDER BY permitida é no final da UNIÃO e se aplica a toda a UNIÃO, tornando xxx UNION yyy ORDER BY zzzo equivalente a(xxx UNION yyy) ORDER BY zzz
Nicholas Carey

39

Para aplicar a classificação apenas à primeira declaração no UNION, você pode colocá-lo em uma subseleção com UNION ALL (ambos parecem ser necessários no Oracle):

Select id,name,age FROM 
(    
 Select id,name,age
 From Student
 Where age < 15
 Order by name
)
UNION ALL
Select id,name,age
From Student
Where Name like "%a%"

Ou (abordando o comentário de Nicholas Carey), você pode garantir que o SELECT superior seja ordenado e os resultados apareçam acima do SELECT inferior da seguinte forma:

Select id,name,age, 1 as rowOrder
From Student
Where age < 15
UNION
Select id,name,age, 2 as rowOrder
From Student
Where Name like "%a%"
Order by rowOrder, name

4
Sim. Isso ordena os resultados da subseleção. Isso NÃO ordena os resultados da selectinstrução que faz referência à subseleção. De acordo com o padrão SQL, a ordem dos resultados é indefinida, exceto uma order bycláusula explícita . O primeiro selectno seu exemplo provavelmente retorna seus resultados na ordem retornada pela subseleção, mas não é garantido. Além disso, isso * não * garante a ordenação do conjunto de resultados do conjunto union(mesma regra na Norma). Se você estiver dependendo da ordem, será eventualmente mordido.
Nicholas Carey

1
@ Nicolas Carey - quando eu testei inicialmente usando um UNION, ele estava se comportando de maneira imprevisível, como você descreveu, acho que o UNION ALL (pelo menos no Oracle) era necessário para solicitar o SELECT superior acima da parte inferior. No entanto, eu forneci uma alternativa que garante a ordem correta e deve ser independente do banco de dados.
BA TabNabber

Não está trabalhando para mim. Aquele com UNION ALL ainda falha em manter a ordem dentro do primeiro SELECT.
Amit Chigadani

E o problema com a segunda consulta é que ela não elimina os registros duplicados. Como você adicionou outra coluna 'rowOrder', que pode ter um valor diferente nos registros duplicados. O objetivo da UNION contra UNION ALL está perdido.
Amit Chigadani

1
@AmitChigadani A eliminação de duplicatas não fazia parte da pergunta original, mas para isso as cláusulas WHERE podem ser modificadas para garantir a exclusividade. por exemplo: Onde nome como "% a%" E age> = 15
BA TabNabber

12

Ambas as outras respostas estão corretas, mas achei interessante notar que o local em que fiquei preso não estava percebendo que você precisará da ordem do alias e verifique se o alias é o mesmo para os dois selecionados.

select 'foo'
union
select item as `foo`
from myTable
order by `foo`

observe que estou usando aspas simples no primeiro select, mas backticks para os outros.

Isso lhe dará a classificação que você precisa.


Qual é a importância que você deseja dar ao usar aspas simples no primeiro select e backticks no outro? Idealmente, deve ser consistente.
Nanosoft 17/10

A primeira seleção é um literal; é um cabeçalho como 'NAMES'. A segunda seleção é uma referência a uma tabela. Portanto, sua primeira linha dirá "NOMES" e o restante das linhas serão os nomes reais selecionados na tabela. O ponto é que seu cabeçalho pode muito bem ser a mesma sequência que o nome da coluna na qual você está selecionando e esta é a solução para usar o rótulo desejado sem que ele colide em sua união.
Yevgeny Simkin

2
Após algumas experiências, vejo que o alias mencionado na cláusula ORDER BY deve ser mencionado nas cláusulas SELECT. Você não pode classificar por outra coluna. É claro que você pode contornar isso envolto a coisa toda em um SELECT a, b, c FROM (<insert union query here>) AS x;caso realmente queira evitar retornar a coluna extra.
Wodin 14/0318

11

Order Byé aplicado depois union, basta adicionar uma order bycláusula no final das instruções:

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like '%a%'
Order By name

9

Se eu quiser que o tipo seja aplicado a apenas um da UNION, use Union all:

Select id,name,age
From Student
Where age < 15
Union all
Select id,name,age
From 
(
Select id,name,age
From Student
Where Name like "%a%"
Order by name
)

8

Como outras respostas declararam, 'Ordenar por' após ÚLTIMO Sindicato deve aplicar-se a ambos os conjuntos de dados unidos pelo sindicato.

Eu estava tendo dois conjuntos de dados, mas usando tabelas diferentes, mas as mesmas colunas. 'Order by' após a ÚLTIMA União ainda não funcionou. Usar o ALIAS para a coluna usada em 'classificar por' fez o truque.

Select Name, Address for Employee 
Union
Select Customer_Name, Address from Customer
order by customer_name;   --Won't work

Portanto, a solução é usar o alias 'User_Name':

Select Name as User_Name, Address for Employee 
Union
Select Customer_Name as User_Name, Address from Customer
order by User_Name; 

-1

Pode usar isso:

Select id,name,age
From Student
Where age < 15
Union ALL
SELECT * FROM (Select id,name,age
From Student
Where Name like "%a%")
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.