É possível usar a cláusula SELECT INTO com UNION [ALL]?

154

No SQL Server, ele insere 100 registros, da tabela Customers no tmpFerdeen: -

SELECT top(100)*
INTO tmpFerdeen
FROM Customers

É possível fazer um SELECT INTO através de um UNION ALL SELECT: -

SELECT top(100)* 
FROM Customers
UNION All
SELECT top(100)* 
FROM CustomerEurope
UNION All
SELECT top(100)* 
FROM CustomerAsia
UNION All
SELECT top(100)* 
FROM CustomerAmericas

Não tenho muita certeza de onde adicionar a cláusula INTO.

Ferdeen
fonte
Tem certeza de que precisa de toda a união?
Sfossen
Sim. Como os registros são exclusivos em todas as tabelas.
30230 Ferdeen

Respostas:

214

Isso funciona no SQL Server:

SELECT * INTO tmpFerdeen FROM (
  SELECT top 100 * 
  FROM Customers
  UNION All
  SELECT top 100 * 
  FROM CustomerEurope
  UNION All
  SELECT top 100 * 
  FROM CustomerAsia
  UNION All
  SELECT top 100 * 
  FROM CustomerAmericas
) as tmp
Chris Van Opstal
fonte
1
Também funciona: SELECT top 100 * EM tmpFerdeen FROM Customers UNION All SELECT top 100 * FROM CustomerEurope UNION All SELECT top 100 * FROM CustomerAsia UNION All SELECT top 100 * FROM CustomerAmericas (desculpe, não é possível formatar o sql aqui). Obrigado!
302 Ferdeen
7
Qual é o significado de "as tmp"?
Dave
@chrisVanOpstal, por que você selecionou os 100 melhores? Quando selecionamos todos os registros, ocorre um erro como- "A cláusula ORDER BY é inválida em visualizações, funções embutidas, tabelas derivadas, subconsultas e expressões comuns de tabela, a menos que TOP ou FOR XML também seja especificado.". Por favor, dê alguma solução.
precisa
1
Olá, sobre o que o @Dave perguntou, vejo que a remoção do "as tmp" resulta em um erro "Sintaxe incorreta esperando como id, ou quoted_id". Então, para que é usado?
Ravid Goldenberg
4
@ Dave, petric: no SQL Server, tabelas temporárias precisam receber um nome. Isso é tudo. O tmp não serve para nenhuma outra função além de tornar a instrução SQL válida. No Oracle SQL, por exemplo, isso é opcional.
Wouter
130

Você não precisa de uma tabela derivada para isso.

Basta colocar o INTOdepois do primeiroSELECT

SELECT top(100)* 
INTO tmpFerdeen
FROM Customers
UNION All
SELECT top(100)* 
FROM CustomerEurope
UNION All
SELECT top(100)* 
FROM CustomerAsia
UNION All
SELECT top(100)* 
FROM CustomerAmericas
Martin Smith
fonte
2
Eu discordo - enquanto a resposta acima também está correta, a resposta aceita é mais clara nele é a intenção
Endurium
5
SELECT * INTO tmpFerdeen FROM 
(SELECT top(100)*  
FROM Customers 
UNION All 
SELECT top(100)*  
FROM CustomerEurope 
UNION All 
SELECT top(100)*  
FROM CustomerAsia 
UNION All 
SELECT top(100)*  
FROM CustomerAmericas) AS Blablabal

Este "Blablabal" é necessário

user1006743
fonte
1

Para consultas do MS Access, isso funcionou:

SELECT * INTO tmpFerdeen FROM( 
    SELECT top(100) *
    FROM Customers 
UNION All 
    SELECT top(100) *  
    FROM CustomerEurope 
UNION All 
    SELECT top(100) *  
    FROM CustomerAsia 
UNION All 
    SELECT top(100) *  
    FROM CustomerAmericas
) 

Isso NÃO funcionou no MS Access

SELECT top(100) * 
  INTO tmpFerdeen
  FROM Customers
UNION All
  SELECT top(100) * 
  FROM CustomerEurope
UNION All
  SELECT top(100) * 
  FROM CustomerAsia
UNION All
  SELECT top(100) * 
  FROM CustomerAmericas
Bobby
fonte
1

Eu faria assim:

SELECT top(100)* into #tmpFerdeen
FROM Customers

Insert into #tmpFerdeen
SELECT top(100)* 
FROM CustomerEurope

Insert into #tmpFerdeen
SELECT top(100)* 
FROM CustomerAsia

Insert into #tmpFerdeen
SELECT top(100)* 
FROM CustomerAmericas
Praveen R
fonte
0

O desafio que vejo com a solução:

FROM( 
SELECT top(100) *
    FROM Customers 
UNION
    SELECT top(100) *  
    FROM CustomerEurope 
UNION 
    SELECT top(100) *  
    FROM CustomerAsia 
UNION
    SELECT top(100) *  
    FROM CustomerAmericas
)

é que isso cria um conjunto de dados em janela que residirá na RAM e, em conjuntos de dados maiores, essa solução criará problemas graves de desempenho, pois deve primeiro criar a partição e usar a partição para gravar na tabela temporária.

Uma solução melhor seria a seguinte:

SELECT top(100)* into #tmpFerdeen
FROM Customers

Insert into #tmpFerdeen
SELECT top(100)* 
FROM CustomerEurope

Insert into #tmpFerdeen
SELECT top(100)* 
FROM CustomerAsia

Insert into #tmpFerdeen
SELECT top(100)* 
FROM CustomerAmericas

para selecionar inserir na tabela temporária e adicionar linhas adicionais. No entanto, a desvantagem aqui é se houver alguma linha duplicada nos dados.

A melhor solução seria a seguinte:

Insert into #tmpFerdeen
SELECT top(100)* 
FROM Customers
UNION
SELECT top(100)* 
FROM CustomerEurope
UNION
SELECT top(100)* 
FROM CustomerAsia
UNION
SELECT top(100)* 
FROM CustomerAmericas

Este método deve funcionar para todos os propósitos que requerem linhas distintas. Se, no entanto, você deseja que as linhas duplicadas simplesmente troquem UNION por UNION ALL

Boa sorte!

Chris Peterson
fonte
-1

Talvez tente isso?

SELECT * INTO tmpFerdeen (
SELECT top(100)* 
FROM Customers
UNION All
SELECT top(100)* 
FROM CustomerEurope
UNION All
SELECT top(100)* 
FROM CustomerAsia
UNION All
SELECT top(100)* 
FROM CustomerAmericas)
Ryan
fonte
Faltando o alias de tabela necessário (e se adicionado será o mesmo que a resposta aceite)
Martin Smith
-3

Tente algo assim: Crie a tabela final de objetos, tmpFerdeen, com a estrutura da união.

Então

INSERT INTO tmpFerdeen (
SELECT top(100)* 
FROM Customers
UNION All
SELECT top(100)* 
FROM CustomerEurope
UNION All
SELECT top(100)* 
FROM CustomerAsia
UNION All
SELECT top(100)* 
FROM CustomerAmericas
)
achinda99
fonte
No SQL Server, as tabelas temporárias são criadas dinamicamente. Eu gostaria de fazer isso sem criar uma tabela de objetos final. Obrigado.
26230 Ferdeen