[firebase-br] Aumentar a performance de uma consulta SQL
Ana Virginia da Silva
virginia em farsoft.com.br
Ter Maio 29 18:48:54 -03 2007
Pessoal, imagine a seguinte situação onde eu tenha 3 tabelas:
PRODUTOS, PRECOS, ESTOQUE
Eu preciso linkar as 3 juntas, ok?
Só que eu preciso fazer isto mesmo que os produtos não tenham preço
e nem estoque, ou seja, farei isto usando LEFT OUTER JOIN.
Até aí tudo bem, agora imaginem que eu preciso pegar o preço da tabela
PRECOS,
o estoque data tabela ESTOQUE sem que isto me gere repetições na tabela
PRODUTOS...Mas
isto ocorreria pq tenho mais de uma tabela de preços e mais de uma qtde de
estoque, pois o
estoque é por setor.
usar group by eu não posso pq senão iria me gerar repetições...ja que teria
que incluir
as colunas que mostro.
Olhem o q montei inicialmente...não sei se tem como transformar alguns
blocos
de codigo em views ou storeprocedures...gostaria da ajuda de algum de vcs
para
melhorar isto...pq isto tá horrível: Tem mtos subselects...e pra dar
manutenção
vcs já viram né...
Pelo que sei no caso deste código abaixo, a query estará fazendo
mtas consultas no banco, pois faço uma subselect pra
cada coluna que preciso, como preco_custo, preco_venda, etc...
Qualquer dica será bem vinda!
select
(select l.locacao from produtos_estoque pe,
setores_estoque se, locacoes l
where pe.is_produto=p.id_produto and se.id_setorestoque=pe.is_setorestoque
and l.id_locacao=pe.is_locacao and (se.setor_estoque=:setorestoque2)
and (pe.is_filial=:is_filial)) as locacao
,
(select sum(est.estoque) from produtos_estoque est where
est.is_produto=p.id_produto and (est.is_filial=:is_filial2)) as
estoque_total
,
(select sum(pe.estoque) from produtos_estoque pe,
setores_estoque se where pe.is_produto=p.id_produto
and se.id_setorestoque=pe.is_setorestoque and (se
setor_estoque=:setorestoque)
and (pe.is_filial=:is_filial3)) as estoque_setor,
(select pr.preco_custo from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco1 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco
order by pr.is_produto, tp.id_tabelapreco) as preco_custo
,
(select pr.preco_custoreal from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco2 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco order by pr.is_produto, tp
id_tabelapreco) as preco_custoreal
,
(select pr.preco_venda from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco3 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco order by pr.is_produto, tp
id_tabelapreco) as preco_venda
,
(select pr.preco_minimo from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco4 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco order by pr.is_produto, tp
id_tabelapreco) as preco_minimo
,
(select pr.desconto_maximo from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco5 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco order by pr.is_produto, tp
id_tabelapreco) as desconto_maximo
,
(select pr.desconto_revenda from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco6 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco order by pr.is_produto, tp
id_tabelapreco) as desconto_revenda
,
(select pr.promocao from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco7 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco order by pr.is_produto, tp
id_tabelapreco) as promocao
,
(select pr.preco_dolar from precos pr, tabela_precos tp
where tp.tabelapreco=:tabelapreco8 and pr.is_produto=p.id_produto
and tp.id_tabelapreco=pr.is_tabelapreco order by pr.is_produto, tp
id_tabelapreco) as preco_dolar
,
p.*,
m.*,
C.cor,
GP.grupoproduto,
PA.*
from
Produtos p
LEFT OUTER JOIN
MARCAS M
on M.id_marca=p.is_marca
LEFT OUTER JOIN
CORES C
on C.id_cor=p.is_cor
LEFT OUTER JOIN
grupos_produtos GP
on GP.id_grupoproduto=p.is_grupoproduto
LEFT OUTER JOIN
PRINCIPIO_ATIVO PA
on PA.id_principioativo=p.is_principioativo
WHERE 1=1
Segue abaixo o DDL das tabelas:
CREATE TABLE PRECOS (
ID_PRECO INTEGER NOT NULL,
IS_TABELAPRECO INTEGER NOT NULL,
IS_PRODUTO INTEGER NOT NULL,
PRECO_CUSTO NUMERIC(10,4),
PRECO_CUSTOREAL NUMERIC(10,4),
MARGEM_VENDA NUMERIC(6,2),
PRECO_VENDA NUMERIC(10,4),
PRECO_DOLAR VARCHAR(1),
DESCONTO_MAXIMO NUMERIC(6,2),
DESCONTO_REVENDA NUMERIC(6,2),
MARGEM_MINIMA NUMERIC(6,2),
PRECO_MINIMO NUMERIC(10,4),
PROMOCAO VARCHAR(1),
ULTIMA_ATUALIZACAO DATE
);
CREATE TABLE PRODUTOS (
ID_PRODUTO INTEGER NOT NULL,
IS_GRUPOPRODUTO INTEGER,
IS_MARCA INTEGER,
IS_ST VARCHAR(3),
IS_COR INTEGER,
IS_PRINCIPIOATIVO INTEGER,
IS_PRODUTOCATEGORIA INTEGER,
ID_SIMILAR INTEGER,
TIPO VARCHAR(1) NOT NULL,
REFERENCIA VARCHAR(15),
CODIGO_INTERNO VARCHAR(15),
BARCODE VARCHAR(13),
DESCRICAO VARCHAR(60) NOT NULL COLLATE PT_PT,
DESCRICAO_RESUMIDA VARCHAR(25) COLLATE PT_PT,
UN VARCHAR(3),
EMBALAGEM NUMERIC(10,3),
IPI NUMERIC(3,2),
CST_A VARCHAR(1),
CST_B VARCHAR(2),
CF VARCHAR(8),
APLICACAO BLOB SUB_TYPE 1 SEGMENT SIZE 8192,
PESO NUMERIC(4,4),
DATA_CADASTRO DATE NOT NULL,
ATIVO VARCHAR(1),
BRASINDICE_APRES VARCHAR(5),
BRASINDICE_ITEM VARCHAR(5),
BRASINDICE_LAB VARCHAR(5),
DESCRICAOFONETICO VARCHAR(60) COLLATE PT_PT,
PSICOTROPICO VARCHAR(1),
PRONTO_SOCORRO VARCHAR(1),
CODIGO_BRASINDICE VARCHAR(10)
);
CREATE TABLE PRODUTOS_ESTOQUE (
ID_PRODUTOESTOQUE INTEGER NOT NULL,
IS_PRODUTO INTEGER NOT NULL,
IS_SETORESTOQUE INTEGER NOT NULL,
ESTOQUE NUMERIC(18,3) NOT NULL,
ESTOQUE_MINIMO NUMERIC(18,3),
ESTOQUE_MAXIMO NUMERIC(18,3),
IS_LOCACAO INTEGER,
IS_FILIAL INTEGER NOT NULL
);
Mais detalhes sobre a lista de discussão lista