Mostrando postagens com marcador SQL. Mostrar todas as postagens
Mostrando postagens com marcador SQL. Mostrar todas as postagens

domingo, 26 de agosto de 2012

Operador UNION e UNION ALL - união de queries

Operador UNION
união de query's, juntar, unir, atrelar, conectar, ligar, acoplar, vincular... várias queries em um único resultado, juntando o select num moido só...


Descrição:
Este operador possibilita a combinação de uma ou mais queries em um único resultado consistindo todas as linhas pertencentes a todas as querys neste união. Veja que isto é diferente de usar JOIN'sque combinam colunas de diferentes tabelas

Regras:
Duas regras básicas para o uso do UNION
- O número e a ordem das colunas deve ser identico em todas as queries
- O tipo de dados deve ser compativel, caso náo for, uma dica seria converter tudo pra varchar usando a função convert

Opções:
Temos a opção de definir a união total com UNION ALL ou somente a união simples com UNION, vejamos abaixo as diferenças:
- UNION: faz a união e já elimina linhas idênticas
- UNION ALL: faz a união e mantém as linhas idênticas
No exemplo abaixo veremos melhor esta a diferença.

Exemplo:
Vamos fazer a união das tabelas clientes e fornecedores, somente com o campo 'Nome', note que o registro "Vito Corleone" (ele mesmo Don Vito, o poderoso Chefão), aparece na tabela de clientes e fornecedores, logo em UNION ele vai aparecer uma única vez e em UNION ALL ele vai aparecer duas vezes.

tabelas para testes
--configurando para não aparecer o contador de registros executados 
set nocount on
--declarando tabelas temporarias para teste
declare @tbClientes table (cod int identity, nome varchar(30))
declare @tbFornecedores table (cod int identity, nome varchar(30))
                  
--inserindo dados na tabela clientes
insert into @tbClientes (nome) values ('Vito Corleone')
insert into @tbClientes (nome) values ('Bonasera')
insert into @tbClientes (nome) values ('Luca Brasi')
                  
--inserindo dados na tabela fornecedores
insert into @tbFornecedores (nome) values ('Paul Vitti')
insert into @tbFornecedores (nome) values ('Tonny Gordo')
insert into @tbFornecedores (nome) values ('Vito Corleone')

.
.
.
.

UNION
--executando o UNION 
select nome from @tbClientes
union
select nome from @tbFornecedores
order by nome
Resultado, observe que Vito Corleone aparece apenas uma única vez:
nome
------------------------------
Bonasera
Luca Brasi
Paul Vitti
Tonny Gordo
Vito Corleone

.
.
.
.
UNION ALL

--executando o UNION ALL
select nome from @tbClientes
union all
select nome from @tbFornecedores
order by nome

Resultado, observe que Vito Corleone aparece duas vezes:
nome
------------------------------
Bonasera
Luca Brasi
Paul Vitti
Tonny Gordo
Vito Corleone
Vito Corleone


OBS:
- Para a ordenação o comando ORDER BY tem que ficar após o último SELECT
- No exemplo citado para as construções UNION foram usadas duas query's, mas poderiamos ter usado N query's


AUTOR: "eriva_br"
Dúvidas, criticas, contribuições, correções e adições seram bem vindas. 

quarta-feira, 27 de julho de 2011

utilizando o comando Merge - mesclando dados entre tabelas

O comando TSQL MERGE é uma novidade do sql 2008, 

O MERGE permite verificações entre as tabelas de origem e destino e promete melhor desempenho na utilização de INSERT, UPDATE e DELETE em certos casos. 

Obs.: as tabelas não necessitam ter exatamente a mesma estrutura, claro que se tiver melhor será para a resolução do problema.

Sua criação é relativamente simples, seus principais 'sub-comandos' são: 
MERGE: define a tabela alvo da operação, a tabela principal, o destino dos dados. 
USING: define a origem dos dados, pode ser tabela, view ou sub-query
ON: realiza a ligação das tabelas
e suas principais ações: (no comando não é obrigatório que se use os 3, pode-se usar somente 1 ou 2 deles)
WHEN MATCHED: quando encontra os dados nas duas tabelas, nesse caso por exemplo podes fazer um update em alguns campos na tabela destino
WHEN NOT MATCHED BY TARGET: quando os dados existem na tabela origem, mas não são encontrados na tabela destino, nesse caso por exemplo podes fazer um insert na tabela destino com os dados da tabela origem
WHEN NOT MATCHED BY SOURCE: o inverso, ou seja, quando os dados existem na tabela destino, mas não são encontrados na tabela de origem, nesse caso por exemplo podes fazer um delete na tabela destino
Obs.: podemos adicionar condições extras juntos com as opções WHEN, por exemplo "WHEN NOT MATCHED BY TARGET and source.saldo > 750 THEN"

agora um exemplo prático para melhor entendimento.

tabelas para testes:
create table tb_cliente (id int primary key, nome varchar(30), saldo money, dt_modificacao date)
insert tb_cliente (id, nome, saldo, dt_modificacao ) values (1, 'Brazil', 1000, null)
insert tb_cliente (id, nome, saldo, dt_modificacao ) values (2, 'Espanha', 2000, null)
insert tb_cliente (id, nome, saldo, dt_modificacao ) values (3, 'France', 3000, null)

create table tb_novos_clientes (id int primary key, nome varchar(30), saldo money)
insert tb_novos_clientes (id, nome, saldo) values (1, 'Brazil', 1500)
insert tb_novos_clientes (id, nome, saldo) values (2, 'Spain', 3000)
insert tb_novos_clientes (id, nome, saldo) values (4, 'England', 800)
insert tb_novos_clientes (id, nome, saldo) values (5, 'Argentina', 700)
insert tb_novos_clientes (id, nome, saldo) values (6, 'Germany', 80)


o comando MERGE:
MERGE tb_cliente AS target
USING (select * from tb_novos_clientes where saldo > 100) AS source --ou então poderiamos colocar somente a tabela tb_novos_clientes
ON (target.id = source.id)
WHEN MATCHED THEN 
UPDATE SET dt_modificacao = GETDATE(),
nome = source.nome,
saldo = source.saldo
WHEN NOT MATCHED BY TARGET and source.saldo > 750 THEN     
INSERT (id, nome, saldo)
VALUES (id, nome, saldo)
WHEN NOT MATCHED BY SOURCE THEN
DELETE 
OUTPUT INSERTED.*, $action, DELETED.*;

o antes e o depois, com dados que sofreram alterações e novos dados, retornados com ajuda do nosso grande amigo OUTPUT, isso você pode colocar por exemplo em uma outra tabela de log. 
id   nome    saldo   dt_modific $actio id   nome    saldo   dt_mod---- ------- ------- ---------- ------ ---- ------- ------- ------
1    Brazil  1500,00 2010-05-30 UPDATE 1    Brazil  1000,00 NULL2    Spain   3000,00 2010-05-30 UPDATE 2    Espanha 2000,00 NULL
NULL NULL    NULL    NULL       DELETE 3    France  3000,00 NULL4    England  800,00 NULL       INSERT NULL NULL    NULL    NULL(4 row(s) affected)

notamos que: 
- os registros 1-Brazil (campo saldo) e 2-Espanha (campos nome e saldo) foram alterados
- o registro 4-England foi incluído 
- O registro 5-Argentina não foi incluído, pois tem saldo de 700 e colocamos a condição Saldo > 750 no comando WHEN NOT MATCHED BY TARGET
- O registro 6-Germany não foi incluido pois ele tem saldo de 80 e na opção USING adicionamos um sub-select filtrando saldo > 100
- o registro 3-França foi excluído pois não estava na tabela origem 

e por final nossa tabela principal, a de clientes, ficou assim:
id      nome         saldo     dt_modificacao------- ------------ --------- --------------
1       Brazil       1500,00   2010-05-30
2       Spain        3000,00   2010-05-30
4       England      800,00    NULL(3 row(s) affected)



Verificamos que o comando MERGE em alguns casos pode resolver problemas de comparações e cargas entre tabelas rapidamente e com menos esforço que em versões anteriores do sql server, onde tinhamos que utilizar cursores e outros recursos alternativos.


abs

AUTOR: "eriva_br"
Dúvidas, criticas, contribuições, correções e adições serão bem vindas.