In your case an index could perfectly solve your problem without the need to create a VIEW
.
Assuming your data structure is something like:
-- INDIVIDUO
CREATE TABLE tb_individuo
(
id BIGINT NOT NULL,
nome TEXT NOT NULL,
PRIMARY KEY( id )
);
-- SEMELHANCA
CREATE TABLE tb_semelhanca
(
id_a BIGINT NOT NULL,
id_b BIGINT NOT NULL,
valor SMALLINT NOT NULL,
PRIMARY KEY( id_a, id_b ),
FOREIGN KEY ( id_a ) REFERENCES tb_individuo ( id ),
FOREIGN KEY ( id_b ) REFERENCES tb_individuo ( id )
);
Containing the following sample data:
-- INSERE 5 INDIVIDUOS
INSERT INTO tb_individuo ( id, nome ) VALUES ( 1, 'JOSE' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 2, 'JOAO' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 3, 'ANTONIO' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 4, 'MARIO' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 5, 'PEDRO' );
-- INSERE SEMELHANCAS ENTRE OS INDIVIDUOS
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 2, 5 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 3, 13 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 4, 27 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 5, 98 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 2, 3, 54 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 2, 4, 63 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 2, 5, 77 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 3, 4, 85 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 3, 5, 42 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 4, 5, 33 );
I suggest creating an index in the field valor
table tb_semelhanca
:
-- CRIACAO DE INDICE NO GRAU DE SEMELHANCA
CREATE INDEX ON tb_semelhanca ( valor );
What would enable queries using a BETWEEN
to recover the desired intevalo with enough agility:
-- CONSULTA USANDO O INDICE
SELECT
a.id,
a.nome,
b.id,
b.nome,
s.valor
FROM
tb_semelhanca AS s
JOIN
tb_individuo AS a ON ( a.id = s.id_a )
JOIN
tb_individuo AS b ON ( b.id = s.id_b )
WHERE
s.valor BETWEEN 20 AND 50;
Exit:
| id | nome | id | nome | valor |
|----|---------|----|-------|-------|
| 1 | JOSE | 4 | MARIO | 27 |
| 4 | MARIO | 5 | PEDRO | 33 |
| 3 | ANTONIO | 5 | PEDRO | 42 |
Sqlfiddle: http://sqlfiddle.com/#! 17/da827/1
EDIT
If the need to create a "summary" is something mandatory, I still do not see the need to create a VIEW
or auxiliary table.
As the cardinality of sumário
with the semelhanca
would be of 1-para-1
, the simple creation of a tb_semelhanca
could solve the problem, let’s see:
-- INDIVIDUO
CREATE TABLE tb_individuo
(
id BIGINT NOT NULL,
nome TEXT NOT NULL,
PRIMARY KEY( id )
);
-- SEMELHANCA
CREATE TABLE tb_semelhanca
(
id_a BIGINT NOT NULL,
id_b BIGINT NOT NULL,
valor SMALLINT NOT NULL,
sumario SMALLINT NOT NULL,
PRIMARY KEY( id_a, id_b ),
FOREIGN KEY ( id_a ) REFERENCES tb_individuo ( id ),
FOREIGN KEY ( id_b ) REFERENCES tb_individuo ( id )
);
The index would be created in the field sumario
of tb_semelhanca
:
-- CRIACAO DE INDICE NO sumario
CREATE INDEX ON tb_semelhanca ( sumario );
One TRIGGER FUNCTION
would be responsible for calculating the summary:
CREATE OR REPLACE FUNCTION calcular_sumario() RETURNS TRIGGER AS
$BODY$
BEGIN
NEW.sumario = (NEW.valor / 10)::int * 10;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
One TRIGGER
would be created to trigger the function calcular_sumario()
every time a modification of the tb_semelhança
:
-- CRIANDO TRIGGER
CREATE TRIGGER trigger_sumario BEFORE INSERT OR UPDATE ON tb_semelhanca FOR EACH ROW EXECUTE PROCEDURE calcular_sumario();
Populating tables:
-- INSERE 10 INDIVIDUOS
INSERT INTO tb_individuo ( id, nome ) VALUES ( 1, 'JOSE' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 2, 'JOAO' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 3, 'ANTONIO' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 4, 'MARIO' );
INSERT INTO tb_individuo ( id, nome ) VALUES ( 5, 'PEDRO' );
-- INSERE SEMELHANCAS ENTRE OS INDIVIDUOS
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 2, 5 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 3, 13 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 4, 27 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 1, 5, 98 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 2, 3, 54 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 2, 4, 63 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 2, 5, 77 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 3, 4, 85 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 3, 5, 42 );
INSERT INTO tb_semelhanca ( id_a, id_b, valor ) VALUES ( 4, 5, 33 );
Checking out tb_semelhanca
:
| id_a | id_b | valor | sumario |
|------|------|-------|---------|
| 1 | 2 | 5 | 0 |
| 1 | 3 | 13 | 10 |
| 1 | 4 | 27 | 20 |
| 1 | 5 | 98 | 90 |
| 2 | 3 | 54 | 50 |
| 2 | 4 | 63 | 60 |
| 2 | 5 | 77 | 70 |
| 3 | 4 | 85 | 80 |
| 3 | 5 | 42 | 40 |
| 4 | 5 | 33 | 30 |
Consultation through the summary:
-- CONSULTA USANDO O SUMARIO
SELECT
a.id,
a.nome,
b.id,
b.nome,
s.valor
FROM
tb_semelhanca AS s
JOIN
tb_individuo AS a ON ( a.id = s.id_a )
JOIN
tb_individuo AS b ON ( b.id = s.id_b )
WHERE
s.sumario = 20;
Exit:
| id | nome | id | nome | valor |
|----|------|----|-------|-------|
| 1 | JOSE | 4 | MARIO | 27 |
Sqlfiddle: http://sqlfiddle.com/#! 17/7e62f/5
this table that has 3 rails undergoes some kind of update or Insert? is a statistic value?
– HudsonPH
Hudson:
"Saliento que essa minha população será praticamente fixa (após o BD ser totalmente populado, espera-se que seja feito quase nenhum acréscimo)"
. It would only work with View if the query to be executed is always the same, without the need to apply conditions, otherwise it gets very bad. I think there could be a new table, that with a Trigger make the similarity ratio for each subject– Rovann Linhalis
Have you ever thought of creating indexes based on expressions ? It seems to be the case that Postgreesql seems to support https://www.postgresql.org/docs/9.1/static/indexes-expressional.html
– Motta
@Hudsonph, this table will not be updated, however, will have Inserts whenever a new individual is inserted in the list of individuals (after the table created and fully populated, it may be necessary to insert a hit or two, but rarely).
– Wandré Veloso
@Motta, I will study this possibility. For now I have created 2 indexes: one for each individual column (to find them in the middle of the huge list).
– Wandré Veloso
@Rovannlinhalis. So, from what I understand, for you, a view wouldn’t be interesting because you have to keep making new queries every time I run (like, always wanting to change which individual I want to return), right? Now, I don’t understand how Trigger would be useful.
– Wandré Veloso
If you can show the example of the calculation of its "summary", in the answer of the lacobus I commented on the Trigger
– Rovann Linhalis