Usuário com melhor resposta
Junção de 02 Query

Pergunta
-
Boa tarde
---EXTRAINDO OS DADOS PARA A CLIENTES
CALL_CENTER_OLTP
.DBO.CLIENTES CLIENTES WHERE ASSOCIADOS.id_associado = CLIENTES.id_associado--Inserinfo dados na dimensao Clientes
A primeira query pega os dados de banco de dados(CRM)das tabela clientes e Associados e insere e um tabela temporaria #CLIENTES.
A segunda query pega esse dados da tabela Temporaria(#cliente) e joga em uma outro banco de Dados(CRM_DW) na tabela Dimensao_cliente.
Como juntas essa dus query sem usar uma tabela temporaria ?
Agradeço
Respostas
-
INSERT INTO dimensao_cliente (nome, sexo, maior_de_idade, dimensao_empresa_id_empresa)
SELECT DISTINCT nome, descricao_sexo, eh_maior_idade, id_empresa
FROM (SELECT id_cliente, nome, sexo, data_nascimento, razao_social, nome_fantasia, setor_economico
FROM CALL_CENTER_OLTP.DBO.ASSOCIADOS ASSOCIADOS,CALL_CENTER_OLTP.DBO.CLIENTES CLIENTES
WHERE ASSOCIADOS.id_associado = CLIENTES.id_associado) As Tab
INNER JOIN dimensao_empresa
ON (Tab.razao_social = dimensao_empresa.razao_social)
WHERE NOT EXISTS ( SELECT * FROM dimensao_cliente
WHERE dimensao_cliente.nome = Tab.nome) -
Boa Noite,
Acredito que uma CTE vá de encontro a clareza do código e a sua necessidade. Tente o código abaixo:
Code SnippetWITH
CLIENTES AS (SELECT
id_cliente, nome, sexo, data_nascimento, razao_social, nome_fantasia, setor_economicoFROM
CALL_CENTER_OLTP.DBO.ASSOCIADOS ASSOCIADOS,CALL_CENTER_OLTP
.DBO.CLIENTES CLIENTESWHERE
ASSOCIADOS.id_associado = CLIENTES.id_associado)INSERT
INTO dimensao_cliente (nome, sexo, maior_de_idade, dimensao_empresa_id_empresa)SELECT
DISTINCT nome, descricao_sexo, eh_maior_idade, id_empresaFROM
CLIENTES, dimensao_empresaWHERE
( CLIENTES.razao_social = dimensao_empresa.razao_social )AND
NOT EXISTS ( SELECT * FROM dimensao_clienteWHERE
dimensao_cliente.nome = CLIENTES.nome)[ ]s,
Gustavo
Todas as Respostas
-
INSERT INTO dimensao_cliente (nome, sexo, maior_de_idade, dimensao_empresa_id_empresa)
SELECT DISTINCT nome, descricao_sexo, eh_maior_idade, id_empresa
FROM (SELECT id_cliente, nome, sexo, data_nascimento, razao_social, nome_fantasia, setor_economico
FROM CALL_CENTER_OLTP.DBO.ASSOCIADOS ASSOCIADOS,CALL_CENTER_OLTP.DBO.CLIENTES CLIENTES
WHERE ASSOCIADOS.id_associado = CLIENTES.id_associado) As Tab
INNER JOIN dimensao_empresa
ON (Tab.razao_social = dimensao_empresa.razao_social)
WHERE NOT EXISTS ( SELECT * FROM dimensao_cliente
WHERE dimensao_cliente.nome = Tab.nome) -
-
-
-
Boa Noite,
Acredito que uma CTE vá de encontro a clareza do código e a sua necessidade. Tente o código abaixo:
Code SnippetWITH
CLIENTES AS (SELECT
id_cliente, nome, sexo, data_nascimento, razao_social, nome_fantasia, setor_economicoFROM
CALL_CENTER_OLTP.DBO.ASSOCIADOS ASSOCIADOS,CALL_CENTER_OLTP
.DBO.CLIENTES CLIENTESWHERE
ASSOCIADOS.id_associado = CLIENTES.id_associado)INSERT
INTO dimensao_cliente (nome, sexo, maior_de_idade, dimensao_empresa_id_empresa)SELECT
DISTINCT nome, descricao_sexo, eh_maior_idade, id_empresaFROM
CLIENTES, dimensao_empresaWHERE
( CLIENTES.razao_social = dimensao_empresa.razao_social )AND
NOT EXISTS ( SELECT * FROM dimensao_clienteWHERE
dimensao_cliente.nome = CLIENTES.nome)[ ]s,
Gustavo
-
-
Oi Jr.
De fato eu basicamente fiz a transposição da consulta para uma CTE e não me atentei para a junção. Com certeza junções com JOINs são mais recomendadas, mas acredito que se a idéia é melhorar, nem o JOIN seria necessário. Um Exists iria melhorar ainda mais, inclusive retirando o DISTINCT. Acredito que o exemplo abaixo seja o mais indicado:
Code SnippetWITH
CLIENTES AS (SELECT
id_cliente, nome, sexo, data_nascimento, razao_social, nome_fantasia, setor_economicoFROM
CALL_CENTER_OLTP.DBO.ASSOCIADOS ASSOCIADOS,CALL_CENTER_OLTP
.DBO.CLIENTES CLIENTESWHERE
ASSOCIADOS.id_associado = CLIENTES.id_associado)INSERT
INTO dimensao_cliente (nome, sexo, maior_de_idade, dimensao_empresa_id_empresa)SELECT
nome, descricao_sexo, eh_maior_idade, id_empresaFROM
CLIENTESWHERE
EXISTS
(SELECT * from dimensao_empresa WHERE CLIENTES.razao_social = dimensao_empresa.razao_social)AND
NOT EXISTS ( SELECT * FROM dimensao_clienteWHERE
dimensao_cliente.nome = CLIENTES.nome)[ ]s,
Gustavo
-
-
-
vc poderia me exlicar melhor esse comando WITH ????????????
Essa seria a melhor maneira de tirar a tabela temporaria entre essas Query ???. Pois tem varios exemplos que preciso fazer isso, e tem caso que antes de inserir em outro banco de dados, preciso fazer o tratamento dos registros, por exemplo:
ALTER
TABLE #ATENDENTES ADD descricao_sexo varchar(10), nome_localidade varchar(50), sigla_estado varchar(2)UPDATE #ATENDENTES SET descricao_sexo = 'Masculino'
WHERE sexo = 'M'
UPDATE #ATENDENTES SET descricao_sexo = 'Feminino'
WHERE sexo = 'F'
como ficaria em uma unica procedure ?
Seria grato,
-
Boa Tarde,
Postei uma observação no outro post.
Se você vai alterar uma estrutura, então a CTE não será útil para adicionar essas colunas. Em todo caso não tínhamos como saber, pois, o script anterior não demonstrava esses comandos de alteração. Ainda assim eu optaria pela CTE e calcularia esses campos. Ex:
SELECT
*, CASE SEXO WHEN 'M' THEN 'Masculinho' ELSE 'Feminino' END AS Descricao_Sexo FROM CTEEvite utilizar tabelas temporárias em processamentos de carga. Elas vão retardar o processo. Podem ter alguns benefícios na clareza do processo mas nem sempre eles compensam o Overhead de escrita (principalmente para tabelas muito grandes)
Suas dúvidas são muitos semelhantes. Que tal se mantivéssemos as dúvidas no mesmo post ?
[ ]s,
Gustavo
-
Desculpa Gustavo, por não ter postado esse tratamento antes, pois a dúvida vai surgindo a medida que vou fazer as query. Entao poderia usar esse Script dentro de uma procedure antes de inserir em outro banco ? Como ficaria essa query com a anterior que vc postou dentro de uma Stored Procedure. Desculpa mais uma vez. Pois sou um pouco inciantes nisso.
SELECT *, CASE SEXO WHEN 'M' THEN 'Masculinho' ELSE 'Feminino' END AS Descricao_Sexo FROM CTE
Grato...
-
Oi Gildo,
A CTE (Common Table Expression) é definida no WITH e é um objeto como uma tabela. Basta colocar um CASE. Adaptando o seu script temos:
Code SnippetWITH
CLIENTES AS (SELECT
id_cliente, nome, sexo, data_nascimento, razao_social, nome_fantasia, setor_economicoFROM
CALL_CENTER_OLTP.DBO.ASSOCIADOS ASSOCIADOS,CALL_CENTER_OLTP
.DBO.CLIENTES CLIENTESWHERE
ASSOCIADOS.id_associado = CLIENTES.id_associado)INSERT
INTO dimensao_cliente (nome, sexo, maior_de_idade, dimensao_empresa_id_empresa)SELECT
DISTINCT nome,case
sexo when 'm' then 'masculino' else 'feminino' end,
eh_maior_idade, id_empresaFROM
CLIENTES, dimensao_empresaWHERE
( CLIENTES.razao_social = dimensao_empresa.razao_social )AND
NOT EXISTS ( SELECT * FROM dimensao_clienteWHERE
dimensao_cliente.nome = CLIENTES.nome)Colocar esse caso é bem mais eficiente do que escrever em uma tabela temporária e atualizar as descrições.
[ ]s,
Gustavo
-
Gustavo
Bom dia
Nos Posts anteriores vc me ensinou a suar o comando With(não precisava usar a tabela temporaria). Posso usar esse comando para referenciar mais de uma tabela ? Estou com essa situação abaixo.Tenho agora varias tabelas temporarias. Os Comando que vc me ensinou WITH, funcioou certinho, quando eu tinha somente uma tabela temporaria.
Grato,
dimensao_cliente_id_cliente
, dimensao_atendente_id_atendente, quantidade, duracao) SELECT dimensao_status.id_status, dimensao_dia.id_tempo, dimensao_cliente.id_cliente,dimensao_atendente
.id_atendente, 1, duracao FROM #CHAMADAS, #DATAS, #ATENDENTES, #STATUS, #CLIENTES,dimensao_dia
, dimensao_mes, dimensao_atendente, dimensao_status, dimensao_cliente, dimensao_empresa,dimensao_central
WHERE (#CHAMADAS.id_funcionario = #ATENDENTES.id_funcionario) AND (#CHAMADAS.id_cliente = #CLIENTES.id_cliente) AND (#CHAMADAS.id_status_chamada = #STATUS.id_status_chamada) AND (#CHAMADAS.data_hora_inicio = #DATAS.data_hora_inicio) AND (#STATUS.descricao = dimensao_status.descricao) AND (#ATENDENTES.nome = dimensao_atendente.nome) AND (#ATENDENTES.nome_localidade = dimensao_central.localidade AND #ATENDENTES.sigla_estado = dimensao_central.sigla_estado) AND (dimensao_atendente.dimensao_central_id_central = dimensao_central.id_central) AND (#CLIENTES.razao_social = dimensao_empresa.razao_social) AND (#CLIENTES.nome = dimensao_cliente.nome) AND (dimensao_cliente.dimensao_empresa_id_empresa = dimensao_empresa.id_empresa) AND (#DATAS.dia = dimensao_dia.dia) AND (#DATAS.ano = dimensao_mes.ano AND #DATAS.mes = dimensao_mes.mes) AND (dimensao_dia.dimensao_mes_id_mes = dimensao_mes.id_mes) -
Bom Dia,
Sim. É possível utilizar quantas tabelas você desejar (no artigo que lhe indique inclusive tem um exemplo desses usando um JOIN dentro de uma CTE). Você poderá inclusive reaproveitar CTEs. Ex:
WITH CTE1 AS (<Coloque aqui o seu SELECT>),
CTE2 AS (<Coloque aqui o seu SELECT>),
CTE3 AS (<Coloque aqui o seu SELECT>),
CTE4 AS (<SELECTs combinados das CTEs 1, 2 e 3)
SELECT <Campos> FROM CTE4
[ ]s,
Gustavo
-
Gustavo.. eu conseguir relacionar as minhas tabelas como o comando Whith, como vc me ensinou. Quando vou executar essa procedure, a mesma fica demorando um bom tempo e não executa. Preciso dar um stop para terminar a execução. Vc poderia transcrever a minha qery anterior para o comando with.
Grato,
CREATE PROCEDURE SP_PREENCHE_FATO_CLIENTE
as
begin
with
CLIENTE as (SELECT
CODCLI,NOMECLI,SEXOCLI FROM CRM.DBO.CLIENTES AS CLIENTES),ESCOLARIDADE
AS(SELECT
CODESC,NOMEESC FROM CRM.DBO.ESCOLARIDADES AS ESCOLARIDADE),ESTADOCIVIL
AS ( SELECT CODESTC,NOMEESTC FROM CRM.DBO.ESTADOSCIVIS AS ESTADOCIVIL),LOGRADOURO
AS ( select codCli,bairrocli,codCid,nomeCid,codEst,NomeEst from crm.dbo.clientes Cliente,crm
.dbo.Cidades Cidades,crm
.dbo.Estados Estado where Cliente.cidadeCli = Cidades.CodCid and cliente.EstadoCli=Estado.CodEst),PROMOCAO
AS ( SELECT CODCAM,NOMECAM,DTINICIOCAM,DTFIMCAM FROM CRM.DBO.CAMPANHAS AS PROMOCAO)INSERT
INTO FATO_CLIENTE(ID_LOGRADOURO,ID_PROMOCAO
,ID_ESCOLARIDADE
,ID_ESTADO_CIVIL
,ID_CLIENTE
,QUANTIDADE)SELECT
DIMENSAO_LOGRADOURO.ID_LOGRADOURO,DIMENSAO_ESCOLARIDADE
.ID_ESCOLARIDADE,DIMENSAO_PROMOCAO
.ID_PROMOCAO,DIMENSAO_ESTADO_CIVIL
.ID_ESTADO_CIVIL,DIMENSAO_CLIENTE
.ID_CLIENTE,1
FROM
LOGRADOURO,ESCOLARIDADE
,PROMOCAO,ESTADOCIVIL,CLIENTE,DIMENSAO_ESCOLARIDADE
,DIMENSAO_PROMOCAO
,DIMENSAO_ESTADO_CIVIL
,DIMENSAO_CLIENTE
,DIMENSAO_LOGRADOURO
WHERE
(PROMOCAO.CODCAM = DIMENSAO_PROMOCAO.ID_PROMOCAO)AND
(CLIENTE.CODCLI = DIMENSAO_CLIENTE.ID_CLIENTE)AND
(ESCOLARIDADE.CODESC = DIMENSAO_ESCOLARIDADE.ID_ESCOLARIDADE)AND
(ESTADOCIVIL.CODESTC = DIMENSAO_ESTADO_CIVIL.ID_ESTADO_CIVIL)AND
(LOGRADOURO.CODCID = DIMENSAO_LOGRADOURO.ID_LOGRADOURO)END
-
Boa Tarde,
Primeiro recomendo que você tire o prefixo sp_ do nome da sua SP. Toda vez que uma procedure tem o prefixo sp_ automaticamente ela será procurada primeiramente no banco MASTER para depois ser procurado no banco atual. Essa ida ao Master provoca um pequeno DELAY desnecessário.
Quantos registros tem cada consulta utilizada no WITH ? As colunas ID possuem índices ?
[ ]s,
Gustavo
-
-
Olá Gildo,
Se há 100 registros e cada um com sua chave primária essa consulta deveria ser muito rápida. Não há nenhum processo que esteja bloqueando você ? Não há nenhuma transação que tenha ficado aberta ? Não era para demorar
[ ]s,
Gustavo
-
Gustavo
Boa noite
Estou com essa query da minha tabela Fato e está me retornando 300 mil registros... essa query esta fazendo um plano cartesiano. 87 x 17 x 20 para cada registro da tabela Promoção. Como resolver isso ? Agradeço
use crm_dw
CREATE PROCEDURE PREENCHE_FATO_CLIENTE
as
begin
with CLIENTE as (
SELECT CODCLI,NOMECLI,SEXOCLI
FROM CRM.DBO.CLIENTES AS CLIENTES),
ESCOLARIDADE AS(
SELECT CODESC,NOMEESC
FROM CRM.DBO.ESCOLARIDADES AS ESCOLARIDADE),
ESTADOCIVIL AS (
SELECT CODESTC,NOMEESTC
FROM CRM.DBO.ESTADOSCIVIS AS ESTADOCIVIL),
--LOGRADOURO AS (
--select codCli,bairrocli,codCid,nomeCid,codEst,NomeEst
-- from crm.dbo.clientes Cliente,
-- crm.dbo.Cidades Cidades,
-- crm.dbo.Estados Estado),
PROMOCAO AS (
SELECT CODCAM,NOMECAM,DTINICIOCAM,DTFIMCAM
FROM CRM.DBO.CAMPANHAS AS PROMOCAO)
INSERT INTO FATO_CLIENTE(--ID_LOGRADOURO,
ID_PROMOCAO,
ID_ESCOLARIDADE,
ID_ESTADO_CIVIL,
ID_CLIENTE,QUANTIDADE)
SELECT --DIMENSAO_LOGRADOURO.ID_LOGRADOURO,
DIMENSAO_ESCOLARIDADE.ID_ESCOLARIDADE,
DIMENSAO_PROMOCAO.ID_PROMOCAO,
DIMENSAO_ESTADO_CIVIL.ID_ESTADO_CIVIL,
DIMENSAO_CLIENTE.ID_CLIENTE,
1
FROM --LOGRADOURO,
ESCOLARIDADE,PROMOCAO,ESTADOCIVIL,CLIENTE,
DIMENSAO_ESCOLARIDADE,
DIMENSAO_PROMOCAO,
DIMENSAO_ESTADO_CIVIL,
DIMENSAO_CLIENTE
--DIMENSAO_LOGRADOURO
WHERE (PROMOCAO.CODCAM = DIMENSAO_PROMOCAO.ID_PROMOCAO)
AND (CLIENTE.CODCLI = DIMENSAO_CLIENTE.ID_CLIENTE)
AND (ESCOLARIDADE.CODESC = DIMENSAO_ESCOLARIDADE.ID_ESCOLARIDADE)
AND (ESTADOCIVIL.CODESTC = DIMENSAO_ESTADO_CIVIL.ID_ESTADO_CIVIL)
--AND (LOGRADOURO.CODCID = DIMENSAO_LOGRADOURO.ID_LOGRADOURO)
END -
-
-
Olá Gildo,
Segue uma pequena adaptação:
Ao invés de:
Code SnippetFROM
ESCOLARIDADE, DIMENSAO_ESCOLARIDADEWHERE
ESCOLARIDADE.CODESC = DIMENSAO_ESCOLARIDADE.ID_ESCOLARIDADEUse
Code SnippetFROM
ESCOLARIDADEINNER
JOIN DIMENSAO_ESCOLARIDADE ON ESCOLARIDADE.CODESC = DIMENSAO_ESCOLARIDADE.ID_ESCOLARIDADEQuando se usa JOINs você é obrigado a especificar as condições através do operador ON. Quando se usa junção no WHERE, caso a condição seja esquecida a consulta irá rodar da mesma forma incorrendo em produtos cartesianos. Essa é mais uma razão para não utilizar junções em cláusula WHERE. Recomendo que você passe a utilizar JOINs ao invés da construção via cláusula WHERE.
[ ]s,
Gustavo
-