Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General »

consulta en BD relacional

Estas en el tema de consulta en BD relacional en el foro de Bases de Datos General en Foros del Web. Poprque al ingresar un solo registros en una tabla relacional, este registro se le asigna a un solo usuario con su ID, pero el problema ...
  #1 (permalink)  
Antiguo 12/03/2011, 17:41
 
Fecha de Ingreso: julio-2004
Ubicación: Medellin - Colombia.
Mensajes: 12
Antigüedad: 19 años, 9 meses
Puntos: 0
consulta en BD relacional

Poprque al ingresar un solo registros en una tabla relacional, este registro se le asigna a un solo usuario con su ID, pero el problema es que este registro se me duplica para cada uno de los usuarios que tengo en la bas de datos.


Ejemplo:

ctaahor cliente ahocta | cedula | ctaahor
idaho | ctaahor cedula | nombre 1 123 12346
1 12346 123 pepe

la informacion se la asigno a este cliente pero cunado consulto me duplica esta cuenta a los demas usuarios ,sabiendo que solo es para ese cliente.

gracias.

Nota: me gustaria montar la imagen de como tengo la bd per no se.
  #2 (permalink)  
Antiguo 12/03/2011, 18:23
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: consulta en BD relacional

Es muy probable que la sentnecia esté mal escrita, pero es imposible saberlo si no la posteas, porque en realidad no sabemos cómo estás haciendo lo que dices que haces.
Por tu explicación (poco clara) pareciera que en lugar de estar hablando de un INSERT estás hablando de un UPDATE... pero si no muestras el código SQL...
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 12/03/2011, 22:35
 
Fecha de Ingreso: julio-2004
Ubicación: Medellin - Colombia.
Mensajes: 12
Antigüedad: 19 años, 9 meses
Puntos: 0
Respuesta: consulta en BD relacional

Cordial saludo.

esta vez tratare de ser mas claro con el problema:


tengo 4 tablas relacionadas
1. cliente
2. ahocta****cta ahorros
3. ctecta ****cta corriente
4. tipocta

las tablas están relacionadas de la siguiente forma

CREATE TABLE cliente
(
cedula INT NOT NULL,
nom1 VARCHAR(13),
nom2 VARCHAR(13),
ape1 VARCHAR(13),
ape2 VARCHAR(13),
saldo REAL,
INDEX (cedula),
PRIMARY KEY(cedula)
) TYPE = INNODB;

CREATE TABLE ahocta
(
idaho INT NOT NULL,
ctaahor INT,
INDEX (idaho),
PRIMARY KEY(idaho)
) TYPE = INNODB;


CREATE TABLE ctecta
(
idcte INT NOT NULL,
ctacrte INT,
INDEX (idcte),
PRIMARY KEY(idcte)
) TYPE = INNODB;


CREATE TABLE tipocta(
ahocta_idaho INT NOT NULL,
cliente_cedula INT NOT NULL,
ctecta_idcte INT NOT NULL,
PRIMARY KEY(ahocta_idaho, cliente_cedula, ctecta_idcte),
INDEX (ahocta_idaho), INDEX (cliente_cedula), INDEX (ctecta_idcte),
FOREIGN KEY(ahocta_idaho) REFERENCES ahocta(idaho),
FOREIGN KEY(cliente_cedula) REFERENCES cliente(cedula),
FOREIGN KEY(ctecta_idcte) REFERENCES ctecta(idcte)
) TYPE = INNODB;


Para la tabla cliente ingresé los siguiente registros:

mysql> SELECT *FROM cliente;
+----------+-----------+--------+---------+------------+-------+
| cedula | nom1 | nom2 | ape1 | ape2 | saldo |
+----------+-----------+--------+---------+------------+-------+
| 8128 | James | Andreis | Alvarez | Chavarria | 0 |
| 7161 | Francisco | Javier | Alvarez | Alvarez | 0 |
+----------+-----------+--------+---------+------------+-------+

Para la tabla ahocta ingresé los siguiente registros:

mysql> SELECT * FROM ahocta;
+-------+---------+
| idaho | ctaahor |
+-------+---------+
| 1 | 1015125 |
| 2 | 352679 |
| 3 | 352680 |
| 4 | 352690 |
+-------+---------+

mysql> SELECT * FROM tipocta;
+--------------+----------------+--------------+
| ahocta_idaho | cliente_cedula | ctecta_idcte |
+--------------+----------------+--------------+
| 1 | 8128 | 1 |
+--------------+----------------+--------------+

Se supone que el numero de cuenta "1015125" con código "1" le fue asignado SOLAMENTE al usuario con cédula "8128"

Cuando realiza esta consulta :

mysql> SELECT cédula, nom1, ape1, ahocta.ctaahor FROM cliente NATURAL JOIN ahocta WHERE idaho=1;

este es el resultado:

+----------+-----------+---------+---------+
| cedula | nom1 | ape1 | ctaahor |
+----------+-----------+---------+---------+
| 8128 | James | Alvarez | 1015125 |
| 7161 | Francisco | Alvarez | 1015125 |
+----------+-----------+---------+---------+

cuando se supone que solo me debería aparecer un solo registro en este caso el de la cedula "8128".


pero al realizar la siguiente consulta se aparece lo que yo quiero que aparezca:

mysql> SELECT cedula, nom1, ape1, ahocta.ctaahor FROM cliente NATURAL JOIN ahocta WHERE idaho=1 AND cedula="8128";
+---------+-------+---------+---------+
| cedula | nom1 | ape1 | ctaahor |
+---------+-------+---------+---------+
| 8128 | James | Alvarez | 1015125 |
+---------+-------+---------+---------+
1 row in set (0.01 s

pero es obvio ya que lo filtro por cedula.

En conclusión ; No es lógico que si yo le asigno un registro a un solo id, en este caso a el numero de cedula en mención le aparezca asignado o se repita a los demás usuarios de la base de datos.

espero haber sido mas claro y que este código le sirva a muchos usuarios.

Nota: si este código es de su utilidad espero me asignen puntuación


Muchas gracias por su atención prestada.
  #4 (permalink)  
Antiguo 12/03/2011, 22:45
 
Fecha de Ingreso: julio-2004
Ubicación: Medellin - Colombia.
Mensajes: 12
Antigüedad: 19 años, 9 meses
Puntos: 0
Respuesta: consulta en BD relacional

Como data la base de datos esta en myslq y este esta instalado en UBUNTU 10.10
  #5 (permalink)  
Antiguo 13/03/2011, 05:58
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: consulta en BD relacional

Código MySQL:
Ver original
  1. SELECT cédula, nom1, ape1, ahocta.ctaahor
  2. FROM cliente NATURAL JOIN ahocta
  3. WHERE idaho=1;
Está mal planteada...
Tal y como lo describes, la tabla Cliente no se relaciona directamente con Ahocta, sino por medio de otra tabla (tipocta), por lo que la sentencia en esas condiciones genera un producto cartesiano (situación donde cada registro es la combinacion de cada registro de la primera tabla con cada registro de la segunda), en esas condiciones, es lógico que haya al menos dos combinaciones de diferentes usuarios que cumplan la condición.

El problema base pareciera ser que el modelo en sí está mal planeado.

Si tienes un usuario que puede tener más de un tipo de cuenta, en realidad tienes tres tablas o cuatro, pero de otra forma.

Caso 1: Los tipos de cuenta distintos sólo se diferencian por nombre y valores de sus atributos, pero el conjunto de datos de cada cuenta tiene la misma cantidad de atributos.

Cliente(cedula, nom1, nom2, ape1, ape2, saldo)
Cuenta(cuenta_id, descripcion_cta, otros datos)
Cliente_Cuenta(cedula, cuenta_id)

Consulta:
Código MySQL:
Ver original
  1. SELECT cedula, nom1, ape1, cuenta_id, descripcion  
  2. FROM cliente C INNER JOIN cliente_cuenta CC ON C.cedula = CC.cedula
  3. INNER JOIN cuenta CT ON CC.cuenta_id = CT.cuenta:id
  4. WHERE CC.cuenta_ic=1;

Caso 2: Los tipos de cuenta poseen datos de diferente clase, por lo que o no tienen iguales dominios (clases de datos representados) o no son iguales las cantidades de atributos. Se genera una jerarquía con subtipos, siendo Cuenta la tabla principal y las hijas CuentaCorriente y CajAhorros.

Cliente(cedula, nom1, nom2, ape1, ape2, saldo)
Cuenta(cuenta_id)
CajaAhorros(cuenta_id, descripcion_cta, otros datos)
CuentaCorriente(cuenta_id, descripcion_cta, otros datos)
Cliente_Cuenta(cedula, cuenta_id)

Este caso desde el punto de vista es más eficiente y preciso, pero hace las consultas algo complejas, pudiendo tener que resolverse en más de una consulta, y debe hacerse en parte programáticamente (a través de la aplicación), pero en definitiva es el modo usado en los sistemas de este tipo.
El login de este tipo lo primero que hace es buscar todos los tipos de cuenta que el usuario posee y muestra las opciones posibles. Según cual opción sea, variará la tercera tabla consultada y los datos obtenidosrepresentados, pero la consulta base es la misma
Código MySQL:
Ver original
  1. SELECT cedula, nom1, ape1, cuenta_id, descripcion  [, otros datos...]
  2.     cliente C
  3.     INNER JOIN
  4.     cliente_cuenta CC ON C.cedula = CC.cedula
  5.     INNER JOIN
  6.     [tabla de la cuenta según tipo] CT ON CC.cuenta_id = CT.cuenta:id
  7. WHERE CC.cuenta_ic=1;

El modelo como tu lo planteaste exigiría que tengas dos tablas que mantengan la relación N:N:N de clientes, cuentas y tipo de cuenta, porque no puedes definir diferentes referencias para la misma FK, sino exige hacer una tabla donde pones ambas (lo que tu haces), pero eso también haría que el usuario tenga forzosamente ambos tipos si o sí.

Un detalle a tener en cuenta: NATURAL JOIN en SQL no es lo mismo que Junta Natural en el álgebra relacional, o al menos no lo es en MySQL. No los confundas.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #6 (permalink)  
Antiguo 13/03/2011, 22:39
 
Fecha de Ingreso: julio-2004
Ubicación: Medellin - Colombia.
Mensajes: 12
Antigüedad: 19 años, 9 meses
Puntos: 0
Respuesta: consulta en BD relacional

Muchas gracias por tu colaboración, osea que solo necesitaría 3 tablas

y seria de la siguiente manera:

cliente(cédula, nom1, nom2, nom3 saldo)

ctaaho(idaho, numctaaho, cédula)

ctacte(idcte, numctacte, cédula)


cédula; actuaria como llave foránea de las tablas ctacte y ctaaho

la relación es: un cliente puede tener varias cuentas bancarias(ya sean cuenta corriente o cuenta de ahorros) y una cuenta solo puede ser asignada a un cliente.
  #7 (permalink)  
Antiguo 14/03/2011, 03:13
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: consulta en BD relacional

Exacto. Esa sería la idea.
El modelo de tres tablas es un modelo simplificado, y sólo se usa como ejemplo. Los modelos reales son algo más complejos, pero para los efectos de estudios iniciales es suficiente.

Acá te paso un modelo gráfico de BBDD para bancos:



Como puedes ver en la relacion entre Cliente y Tipos de cuenta sólo hay una tabla. El resto de los detalles se maneja como "Servicios"
En este link puedes ver el moldelo con los atributos: http://www.databaseanswers.org/data_...attributes.htm
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #8 (permalink)  
Antiguo 16/03/2011, 08:01
 
Fecha de Ingreso: julio-2004
Ubicación: Medellin - Colombia.
Mensajes: 12
Antigüedad: 19 años, 9 meses
Puntos: 0
Respuesta: consulta en BD relacional

Cordial saludo.

Que pena yo nuevamente con el mismo tema.

mira aca esta la relacion

cliente(cédula, nom1, nom2, ape1)

ctaaho(idaho, ctaaho, cédula)

ctacte(idcte, ctacte, cédula)

cédula; actuaria como llave foránea de las tablas ctacte y ctaaho.


CREATE TABLE cliente
(
cedula INT NOT NULL,
nom1 VARCHAR(13),
nom2 VARCHAR(13),
ape1 VARCHAR(13),
ape2 VARCHAR(13),
PRIMARY KEY(cedula)
) TYPE = INNODB;

CREATE TABLE ctaaho
(
idaho INT NOT NULL,
ctaahor INT,
cedula INT NOT NULL,
PRIMARY KEY(idaho),
INDEX (cedula),
FOREIGN KEY (cedula) REFERENCES cliente(cedula)
) TYPE = INNODB;


CREATE TABLE ctecta
(
idcte INT NOT NULL,
ctacte INT,
cedula INT NOT NULL,
PRIMARY KEY(idaho),
INDEX (cedula),
FOREIGN KEY (cedula) REFERENCES cliente(cedula)
) TYPE = INNODB;


Pero tengo la misma duda ;

A la tabla cliente le asigne a dos clientes

| cedula | nom1 | ape1 |
+---------+-------+-------
| 3215 | Juan | Andres |
| 7161 |Javier| Alvarez |
+---------+-------+-------

A la tabla ctaaho a un cliente le asigne una cta de ahorro de la siguiente manera:


| idaho | ctaahor | cedula |
| 1 | 456789 | 3215 |

cuando hago la siguiente consulta:

SELECT cliente.cedula, cliente.nom1, cliente.ape1, ctaaho.ctaahor FROM cliente, ctaaho

y el resultado de la consulta es la siguiente:

| cedula | nom1 | ape1 | ctaahor |
+---------+-------+-------+-------+-
| 3215 | Juan | Andres | 456789 |
| 7161 |Javier| Alvarez | 456789 |
+---------+-------+-------+-------+-

y el resultado que yo espero o quiero con la consulta seria la siguiente:

| cedula | nom1 | ape1 | ctaahor |
+---------+-------+-------+-------+-
| 3215 | Juan | Andres | 456789 |
| 7161 |Javier| Alvarez | NULL |
+---------+-------+-------+-------+-

Ya que solamente asigne una cuenta a un solo cliente en este caso el que es ta identificado con la cedula = 3215 y el de la cedula = 7161 deberia aparecer NULL o vacio., ya que no tiene cedula asociada.

muchas gracias y disculpe si he repetido la pregunta, pero aun tengo la duda.pese a que he intentado de muchas formas.. en base a las respuestas del foro...

espero haberne hecho entender con la pregunta..
  #9 (permalink)  
Antiguo 16/03/2011, 08:13
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: consulta en BD relacional

Olvidate de la coma a la hora de hacer las consultas. Queda muy bonita en los tutoriales y manuales, pero tiende a producir productos cartesianos y por ende respuestas incorrectas, especialmente cuando (como en tu caso) no le estás poniendo las condiciones de la relación.

Usa INNER JOIN, es más eficiente:
Código MySQL:
Ver original
  1. SELECT c.cedula, c.nom1, c.ape1, ct.ctaahor
  2. FROM cliente c INNER JOIN ctaaho ct ON c.cedula = ct.cedula;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #10 (permalink)  
Antiguo 16/03/2011, 08:29
 
Fecha de Ingreso: julio-2004
Ubicación: Medellin - Colombia.
Mensajes: 12
Antigüedad: 19 años, 9 meses
Puntos: 0
Respuesta: consulta en BD relacional

Justamene estaba haciendo esto antes de lerr es post


SELECT cliente.cedula, cliente.nom1, cliente.ape1, ctaaho.ctaahor FROM cliente INNER JOIN ctaaho ON cliente.cedula=ctaaho.cedula

y el resultado es el siguiente:

| cedula | nom1 | ape1 | ctaahor |
+---------+-------+-------+-------+-
| 3215 | Juan | Andres | 456789 |
| 7161 |Javier| Alvarez | 3525 |
+---------+-------+-------+-------+-

Obviamente le asigne una cta a el usuario con cedula 7161.

pero mi duda es el porque al hacer una consulta normal

se duplica esta informacion asi uno no le haya asignado una cta aun cliente, o toca manualmente colocar null en el campo de algun cliente que no tenga cuenta.

muchas gracias
  #11 (permalink)  
Antiguo 16/03/2011, 08:45
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: consulta en BD relacional

La operación JOIN sin condiciones genera un producto entre las dos tablas, denominado producto cartesiano, donde cada registro de la primera se combina con cada registro de la segunda. Es precisamente por eso que no es una buena práctica y es preferible usar INNER/LEFT/RIGHT JOIN en lugar de comas.
Además, la coma y su equivalente JOIN lo que intentan hacer es combinar haciendo matching sobre campos que tengan el mismo nombre. Si las dos tablas comparten nombres, pero se trata de datos de dominio distinto, MySQL no lo puede saber y el resultado termina siendo erróneo.
De esto surgen algunos consejos:
1) Usa los mismos nombres de columna sólo para los mismos tipos de datos, con el mismo dominio.
2) No uses nombres demasiado genéricos, como ID, CANT, o cosas así. Es mejor ponerles un sufijo o prefijo con el nombre de la tabla, de modo que facilite recordarlos.
3) Cuando uses FK, no le cambies el nombre en la tabla. Usa el mismo nombre que tiene en su tabla de origen; eso permite escribir las consultas con más facilidad y eficiencia.
4) No te olvides de las condiciones de relación (el ON del INNER JOIN), porque de lo contrario el parser no sabrá con seguridad qué estás relacionando.
5) Procura no usar la coma. Como ya viste, tiende a producir errores con facilidad.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #12 (permalink)  
Antiguo 16/03/2011, 08:50
 
Fecha de Ingreso: julio-2004
Ubicación: Medellin - Colombia.
Mensajes: 12
Antigüedad: 19 años, 9 meses
Puntos: 0
Respuesta: consulta en BD relacional

Muchas gracias por la informacion y el tiempo.

cualquier otra inquietud la ahré saber por este medio.. y espero que esta info sirva a usuarios del foro.

Etiquetas: bd, bases-de-datos
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 00:23.