Select N para N

Firebird

09/11/2010

Ola Pessoal

preciso de uma ajuda :  tenho 3 tabelas :

Tabela A
  - controle(integer)
  - nome (string)
 

Tabela B
  - nome (integer)-> chave para relacionamento com A.controle
  - valor
  - tipo

Tabela C
 - nome (integer)->- chave para relacionamento com A.controle
 - valor
 - modo

 preciso exibir em  um grid

 Nome, soma(B.valor) - soma(C.valor)

tentei

  select A.Nome, sum (B.valor) - Sum(C.valor)  from A left join B on controle=B.nome
  left join C on controle=C.nome group by A.Nome
       
  A query abre, mas com valores errados ( C.valor * numero de registros de B)

 com resolver este abacaxi
( relacionamento n para n )

 um  abraco











Cilmar Rosa

Cilmar Rosa

Curtidas 0

Respostas

Ricardo Araujo

Ricardo Araujo

09/11/2010

boa noite, fiz um exemplo:

da uma olhada e ve se ajuda vc :
criei todas as tabelas, estou mandando o todos o código.


// este script e da primeira tabela.
CREATE GENERATOR GEN_TB_A_ID;


CREATE TABLE TB_A (
    ID    INTEGER NOT NULL,
    NOME  VARCHAR(20)
);

ALTER TABLE TB_A ADD CONSTRAINT PK_TB_A PRIMARY KEY (ID);

CREATE OR ALTER TRIGGER TB_A_BI FOR TB_A
ACTIVE BEFORE INSERT POSITION 0
as
begin
  if (new.id is null) then
    new.id = gen_id(gen_tb_a_id,1);
end



//segunda tabela
CREATE GENERATOR GEN_TB_B_ID;

CREATE TABLE TB_B (
    ID     INTEGER NOT NULL,
    TB_A   INTEGER,
    VALOR  NUMERIC(15,2),
    TIPO   INTEGER
);

ALTER TABLE TB_B ADD CONSTRAINT PK_TB_B PRIMARY KEY (ID);

ALTER TABLE TB_B ADD CONSTRAINT FK_TB_B_1 FOREIGN KEY (TB_A) REFERENCES TB_A (ID);

CREATE OR ALTER TRIGGER TB_B_BI FOR TB_B
ACTIVE BEFORE INSERT POSITION 0
as
begin
  if (new.id is null) then
    new.id = gen_id(gen_tb_b_id,1);
end

// script da terceira tabela

CREATE GENERATOR GEN_TB_C_ID;

CREATE TABLE TB_C (
    ID     INTEGER NOT NULL,
    TB_A   INTEGER,
    VALOR  NUMERIC(15,2),
    MODO   INTEGER
);

ALTER TABLE TB_C ADD CONSTRAINT PK_TB_C PRIMARY KEY (ID);

ALTER TABLE TB_C ADD CONSTRAINT FK_TB_C_1 FOREIGN KEY (TB_A) REFERENCES TB_A (ID);

CREATE OR ALTER TRIGGER TB_C_BI FOR TB_C
ACTIVE BEFORE INSERT POSITION 0
as
begin
  if (new.id is null) then
    new.id = gen_id(gen_tb_c_id,1);
end


fiz um exemlo e deu certo, ai está o script final com a soma.

Select  a.nome,
        sum(b.valor) as valor_b,
        sum(c.valor) as valor_c,
        sum(b.valor) - sum(c.valor) as diferenca

  from tb_a a  inner join
       tb_b b on (a.id = b.tb_a) inner join
       tb_c c on (b.tb_a = c.tb_a)

  group by a.nome


agora só criar uma aplicação normal no delphi, e colocar uma query com este codigo, e colocar um dbgrid ligado ao dataset, e o dataset ligado na query.

depois dos componente tudo ligado só executar a aplicação, e tudo estará funcionando.





GOSTEI 0
Emerson Nascimento

Emerson Nascimento

09/11/2010

creio que esse caso somente com subselects:

select
  A.nome,
  coalesce(sum(B.valor),0) valorB,
  (select coalesce(Sum(C.valor),0) from C where C.nome = A.Nome) valorC,

  coalesce(sum(B.valor),0) -
  (select coalesce(Sum(C.valor),0) from C where C.controle = A.Nome) Resultado

from
  A
left join
  B on B.nome=A.nome
group by
  A.Nome
GOSTEI 0
Cilmar Rosa

Cilmar Rosa

09/11/2010

Ainda  Não funciona pessoal

 Continua replicando quando as tabelas B e C tem varios registros cada

  que meleca!


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

09/11/2010

a instrução que eu te passei não replica, não. uso esse tipo montagem constantemente.
GOSTEI 0
Cilmar Rosa

Cilmar Rosa

09/11/2010

Ola Emerson

    Esta correto

     funciona perfeitamente. Foi erro meu ao passar o select

     Obrigado e um abraço

   Cilmar
GOSTEI 0
POSTAR