PDA

Ver la Versión Completa : Encuentro natural al usar dos veces la misma tabla


Caminante
16-05-2012, 23:56:10
Bueno aquí me tiene de nuevo con otra consulta. Utilizo firebird 2.5. Explico mi duda
Trabajo en una distribuidora de gases industriales (llámese oxígeno, nitrógeno, argón, etc.) e implemente un sistema para controlar los movimientos de los cilindros. Nuestro modo de trabajo se basa en prestar cilindros a nuestros distintos clientes que son cilindros propios de la empresa o cilindros que nuestros proveedores nos asignan; pero también se da el caso de que algún cliente nos dé un cilindro de su propiedad como canje. Asi que la tabla de cilindros queda asi:

CREATE TABLE CILINDROS (
ID_CILINDRO INTEGER NOT NULL,
DESCRIPCION VARCHAR(30),
TIPOGAS VARCHAR(10),
CAPACIDAD VARCHAR(5),
PROPIETARIO INTEGER,
OBSCILINDRO VARCHAR(30)
);
ALTER TABLE CILINDROS ADD PRIMARY KEY (ID_CILINDRO);
ALTER TABLE CILINDROS ADD FOREIGN KEY (PROPIETARIO) REFERENCES CLIEPROV (ID_CLIENTE) ON DELETE NO ACTION ON UPDATE CASCADE;

El campo propietario se corresponde con la clave primaria de mi tabla de clientes que está definida así:

CREATE TABLE CLIEPROV (
ID_CLIENTE INTEGER NOT NULL,
RUC VARCHAR(11),
NOMBRE VARCHAR(50) NOT NULL COLLATE ES_ES,
DIRECCION VARCHAR(50),
DISTCLIE INTEGER,
PROVINCIA VARCHAR(30),
EMAIL VARCHAR(30),
WEB VARCHAR(30),
CONTACTO VARCHAR(50),
TIPO INTEGER NOT NULL,
NOMMAYUS VARCHAR(50) COLLATE ES_ES
);
ALTER TABLE CLIEPROV ADD PRIMARY KEY (ID_CLIENTE);
ALTER TABLE CLIEPROV ADD FOREIGN KEY (DISTCLIE) REFERENCES DISTRITOS (ID_DISTRITO) ON DELETE SET DEFAULT ON UPDATE CASCADE;
CREATE INDEX IDXNOMMAYUS ON CLIEPROV (NOMMAYUS);
CREATE INDEX IDXRUC ON CLIEPROV (RUC);

Debido a que se maneja una cantidad minima de proveedores con los mismos campos se guardan clients y proveedores en la misma table diferenciandose por el campo tipo (0 clientes, 1 proveedores)
Bueno he querido listar los movimientos de los cilindros con la siguiente consulta:


SELECT MC.FECHADOC,CI.TIPOGAS,CI.DESCRIPCION,CI.CAPACIDAD, MC.SERIE,MC.DOCUMENTO,
DC.PLAZO,CP1.ID_CLIENTE,CP1.NOMBRE, CP1.TIPO,DC.LUGAR,DC.FECHADEV,DC.DOCDEV,CP2.ID_CLIENTE, CP2.NOMBRE,CP2.TIPO
FROM MOVCILINDROS MC
inner join DETALLECIL DC ON MC.id_mov =DC.movcil
INNER JOIN cilindros CI ON CI.id_cilindro=DC.cil
INNER JOIN clieprov CP1 ON MC.nomdestino=CP1.id_cliente
INNER JOIN clieprov CP2 ON CI.propietario =CP2.id_cliente;


La consulta devuelve los datos deseados y a una buena velocidad aun con más de 10000 registros que devuelve (Es una consulta inicial aun sin aplicarle filtros; lo que pienso hacer). Pero viendo el plan encontré esto:

PLAN JOIN (CP1 NATURAL, MC INDEX (RDB$FOREIGN5), DC INDEX (RDB$FOREIGN12), CI INDEX (RDB$PRIMARY1), CP2 INDEX (RDB$PRIMARY2))

Ósea que hay un encuentro natural en la tabla de Clientes que se utiliza dos veces en la consulta (CP1 cliente a quien se le presto un cilindro; y Cp2 propietario del cilindro). El caso es que al quitar alguna de las referencias dejando solo una tabla ya no me muestra el encuentro natural.
Como dije la consulta se muestra bien pero a futuro cuando la tabla tenga muchos más registros puede que empiecen los problemas.
La verdad no se qué camino debo tomar para solucionar esto. Ya probé crear otro índice para el campo Id_cliente pero sigue igual.
Espero su consejo

Desde ya gracias por la atención prestada

celades1
17-05-2012, 08:04:57
Hola

No enseñas la tabla MOVCILINDROS pero creo que te falta una FOREIGN KEY
nomdestino contra CLIEPROV (ID_CLIENTE)


Saludos

Caminante
17-05-2012, 16:34:20
Si tienes razon aqui esta la definicion. Si defino las claves foraneas


CREATE TABLE MOVCILINDROS (
ID_MOV INTEGER NOT NULL,
NOMDESTINO INTEGER NOT NULL,
SERIE VARCHAR(3) NOT NULL,
DOCUMENTO VARCHAR(10) NOT NULL,
FECHADOC DATE NOT NULL,
VENDEDOR INTEGER NOT NULL
);

ALTER TABLE MOVCILINDROS ADD PRIMARY KEY (ID_MOV);

ALTER TABLE MOVCILINDROS ADD CONSTRAINT FK_MOVCILINDROS_DEST FOREIGN KEY (NOMDESTINO) REFERENCES CLIEPROV (ID_CLIENTE) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE MOVCILINDROS ADD FOREIGN KEY (VENDEDOR) REFERENCES PERSONAL (ID_PERSONAL) ON DELETE NO ACTION ON UPDATE CASCADE;


Agrego q todos los campos incluidos en los joins corresponden con claves foraneas