Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Encuentro natural al usar dos veces la misma tabla (https://www.clubdelphi.com/foros/showthread.php?t=78786)

Caminante 16-05-2012 23:56:10

Encuentro natural al usar dos veces la misma tabla
 
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:

Código SQL [-]
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í:

Código SQL [-]
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:

Código SQL [-]
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:

Código SQL [-]
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


Código SQL [-]
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


La franja horaria es GMT +2. Ahora son las 01:07:53.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi