[SP-pm] Problemas numa comparação

Eden Cardim edencardim at gmail.com
Wed Jul 8 19:40:25 PDT 2009


2009/7/8  <claudio em dpreferencial.com.br>:
> Eu trabalho com processamento de pesquisas de mercado. (tabulação)
>
> No começo trabalhei muito anos com Statiscs SPSS, Statiscs ... (com estes
> programas as bases ficavam realmente gigantes..rsrs..200.000 campos..rsrs)
> acabei desenvolvendo meu próprio sistema de tabulação.
> levando em consideração que:
> - 80% dos campos de uma pesquisa são campos numéricos e RM (respostas
> múltiplas=campos multivalorados)
>   Ex:
>   Quais frutas vc gosta:
>   1 - abacaxi
>   2 - Mamão
>   3 - abacate....  até o código 50.
>
>   um fulano responde os códigos 2/3/4/9/10/15
>
>   num buffer(array de boleanos) eu marco true nestas posição e gravo.
>
> Veja, no SPSS ou em outras bases "normais" eu precisaria de 15 campos para
> guardar as informações,
> quando que eu guardo num campo só..de tamanho bem pequeno...rsrs..

Bom, até aqui, não vejo porque numa base relacional você precisaria de
15 campos, se tivesse um modelo adequado ao seu problema como esse, em
PostgreSQL:

CREATE SEQUENCE person_no_seq INCREMENT BY 1 START WITH 1;
CREATE SEQUENCE question_no_seq INCREMENT BY 1 START WITH 1;
CREATE SEQUENCE field_no_seq INCREMENT BY 1 START WITH 1;

CREATE TABLE person ( id INTEGER DEFAULT nextval('person_no_seq')
PRIMARY KEY, name TEXT NOT NULL);
CREATE TABLE question ( id INTEGER DEFAULT nextval('question_no_seq')
PRIMARY KEY, query TEXT NOT NULL);
CREATE TABLE field ( id INTEGER DEFAULT nextval('field_no_seq')
PRIMARY KEY, name TEXT NOT NULL);
CREATE TABLE answer ( question_id INTEGER REFERENCES question(id),
field_id INTEGER REFERENCES field(id), person_id INTEGER REFERENCES
person(id), UNIQUE(question_id, field_id, person_id) );

INSERT INTO answer (question_id, field_id, person_id) VALUES ((SELECT
id FROM question WHERE query = 'Qual a fruta que você mais gosta?'),
(SELECT id FROM field WHERE name = ''), (SELECT id FROM person WHERE
name = 'Solli'));
INSERT INTO answer (question_id, field_id, person_id) VALUES ((SELECT
id FROM question WHERE query = 'Qual a fruta que você mais gosta?'),
(SELECT id FROM field WHERE name = 'Abacaxi'), (SELECT id FROM person
WHERE name = 'Solli'));
INSERT INTO answer (question_id, field_id, person_id) VALUES ((SELECT
id FROM question WHERE query = 'Qual a fruta que você mais gosta?'),
(SELECT id FROM field WHERE name = 'Uva'), (SELECT id FROM person
WHERE name = 'Solli'));
INSERT INTO answer (question_id, field_id, person_id) VALUES ((SELECT
id FROM question WHERE query = 'Qual a fruta que você mais gosta?'),
(SELECT id FROM field WHERE name = 'Mamão'), (SELECT id FROM person
WHERE name = 'Wesley'));
INSERT INTO answer (question_id, field_id, person_id) VALUES ((SELECT
id FROM question WHERE query = 'Qual a fruta que você mais gosta?'),
(SELECT id FROM field WHERE name = 'Uva'), (SELECT id FROM person
WHERE name = 'Wesley'));

A partir daqui você pode fazer várias consultas:

Por exemplo, tendo o nome da pessoa descobrir quais frutas ela gosta:

SELECT f.name FROM field f JOIN answer a ON a.field_id = f.id JOIN
question q ON a.question_id = q.id JOIN person p on a.person_id = p.id
WHERE p.name = 'Wesley' AND q.query = 'Qual a fruta que você mais
gosta?';
SELECT f.name FROM field f JOIN answer a ON a.field_id = f.id JOIN
question q ON a.question_id = q.id JOIN person p on a.person_id = p.id
WHERE p.name = 'Solli' AND q.query = 'Qual a fruta que você mais
gosta?';
SELECT f.name FROM field f JOIN answer a ON a.field_id = f.id JOIN
question q ON a.question_id = q.id JOIN person p on a.person_id = p.id
WHERE p.name = 'Mantovani' AND q.query = 'Qual a fruta que você mais
gosta?';

E tem um "macete" para "tabular" campos inseridos na tabela "field",
você faz uma pré-consulta:

SELECT f.name FROM field f JOIN answer a ON a.field_id = f.id JOIN
question q ON a.question_id = q.id WHERE q.query = 'Qual a fruta que
você mais gosta?' GROUP BY f.name;

Depois usa os valores de retorno para construir outra consulta:

SELECT p.name,
  SUM((SELECT CASE WHEN f.name = 'Mamão' THEN 1 ELSE 0 END)) AS Mamão,
  SUM((SELECT CASE WHEN f.name = 'Abacate' THEN 1 ELSE 0 END)) AS Abacate,
  SUM((SELECT CASE WHEN f.name = 'Abacaxi' THEN 1 ELSE 0 END)) AS Abacaxi,
  SUM((SELECT CASE WHEN f.name = 'Maçã' THEN 1 ELSE 0 END)) AS Maçã,
  SUM((SELECT CASE WHEN f.name = 'Uva' THEN 1 ELSE 0 END)) AS Uva
FROM field f JOIN answer a ON a.field_id = f.id JOIN person p ON
a.person_id = p.id
GROUP BY p.name;
   name    | mamão | abacate | abacaxi | maçã | uva
-----------+-------+---------+---------+------+-----
 Wesley    |     1 |       0 |       0 |    0 |   1
 Solli     |     1 |       0 |       1 |    0 |   0
 Mantovani |     1 |       0 |       0 |    0 |   0

Claro que o modelo pode ser mais preciso e elaborado, mantive simples
apenas para facilitar a ilustração. As demais consultas ficam como
exercício para o leitor... ;)

> Desenvolvi um formato para o meu arquivo de dados,
> levando em consideração minhas necessidades, tais como:
>
> - conteúdo criptografado.

Se for criptografia da boa, você vai sofrer muito com o desempenho, e
se for da criptografia ruim (xor, etc.), não vale a pena usar.
Geralmente, só se criptografam dados que trafegam em locais públicos e
mesmo assim, segurança é trabalho pro SO e não pro banco de dados.

> - tamanho final do arquivo de base.

Economizar espaço vai fazer você gastar processamento, para
"empacotar" e "desempacotar" os dados. Geralmente é preferível
economizar no processamento porque espaço sempre escala, mas
processamento não.

> - quantidade final de campos na base.
> - base não normalizada = campos multivalorados e dependentes..
> - conteúdo dos campos: numérico.

Irrelevante com um modelo relacional adequado.

Além disso, com uma base de dados relacional de verdade você vai obter
vantagens como garantia de integridade, controle de concorrência,
índices, etc, etc.

Talvez eu não esteja enxergando direito, mas não vejo necessidade de
se implementar um sistema de armazenamento próprio com os requisitos
que você postou aqui a não ser por motivos educacionais.

-- 
   Eden Cardim       Need help with your Catalyst or DBIx::Class project?
  Code Monkey                    http://www.shadowcat.co.uk/catalyst/
 Shadowcat Systems Ltd.  Want a managed development or deployment platform?
http://edenc.vox.com/            http://www.shadowcat.co.uk/servers/


More information about the SaoPaulo-pm mailing list