** NORMAS DEL FORO **
Inicio del foro Inicio del foro > Otros de Microsoft: Windows y Office > Visual Basic Clásico (VB3...VB6)
  Mensajes nuevos Mensajes nuevos RSS - Problemas con relación entre tablas
  Preguntas frecuentes Preguntas frecuentes  Buscar en el foro   Eventos   Registro Registro  Iniciar sesion Iniciar sesion

Tema cerradoProblemas con relación entre tablas

 Responder Responder
Autor
Mensaje
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Tema: Problemas con relación entre tablas
    Enviado: 06/Abril/2015 a las 17:40

Hola

En una base de datos de Access tengo siete (7) tablas:

1-     1-  tabDatosPersonales

2-     2-  tabDatosLaborales

3-     3-  tabMilit

4-     4-  tabEscolaridad

      5- tabTrayectoriaLaboral

6-     6-  tabEscuelasCursadas

7-     7-  tabSanc

Las cuatro primeras tienen siempre la misma cantidad de registros, de modo que, de la 2 a la 4, van a coincidir en su Id con la primera, que vendría siendo la tabla principal.

Las tres tablas restantes (de la 5 a la 7) tienen relación con la tabla principal, pero, la cantidad de registros puede ser superior; de modo que, “x” registros de estas tablas tendrán relación con un registro de la tabla principal. PERO,… entre estas tres tablas, la cantidad de registros puede cambiar. Y es aquí donde está el problema. Al relacionar estas tres tablas y definir su relación, no siempre me muestra la cantidad de registros total que existen en cada una de las tres tablas de manera conjunta, está en dependencia de hacia dónde dirigido el JOIN, si hacia la derecha (RIGHT JOIN) o izquierda (LEFT JOIN), de modo que no he podido definir la relación para obtener todos los registros de estas tres tablas.

Hice una consulta con las cuatro primeras tablas y los resultados son satisfactorios, sin problema alguno. Pero la segunda consulta con las tres restantes tablas, es ahí donde está el problema.

Esta es la consulta:

SELECT tabTrayectoriaLaboral.IdTrayLab, tabTrayectoriaLaboral.TrayLabCentroTrab, tabTrayectoriaLaboral.TrayLabOcupLab, tabEscuelasCursadas.EscCurCurso, tabEscuelasCursadas.EscCurEscuela, tabSanc.SancTipoSan, tabSanc.SancSan,

FROM tabTrayectoriaLaboral RIGHT JOIN (tabEscuelasCursadas LEFT JOIN tabSanc ON (tabEscuelasCursadas.IdEscCur = tabSanc.IdSanc) AND (tabEscuelasCursadas.EscCurDatosPers = tabSanc.SancDatosPers)) ON (tabTrayectoriaLaboral.IdTrayLab = tabEscuelasCursadas.IdEscCur) AND (tabTrayectoriaLaboral.TrayLabDatosPers = tabEscuelasCursadas.EscCurDatosPers);

En los campos:

TrayLabDatosPers

EscCurDatosPers

SancDatosPers

guardo el número que coincida con la tabla principal para saber cuáles registros de estas tres tablas tienen que ver con qué registro de la tabla principal.

Si lograron entenderme, le agradecería cualquier sugerencia.

Gracias

Saludos
Desde La Habana, Cuba
Medardo
Arriba
CSharlie Ver desplegable
Asiduo
Asiduo


Unido: 11/Agosto/2014
Localización: En mi casa
Estado: Sin conexión
Puntos: 288
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 18:22
La clausula FROM está mal creada, las uniones no relacioas los campos de las tablas adecuadas, es decir, si haces un left join de dos tablas a continuación relacionas ambas tablas (ON) mediante un campo, y así con el resto. Te dejo un ejemplo de como relaciono yo 3 tablas que están unidas por un campo distinto la principal con las otras dos y como obtengo los datos, a ver si te sirve.

Las tablas son OTS, INSTRUMENTOS y CERTIFICADOS. Tras hacer una select obteniendo campos de las 3 tablas las relaciono de la siguiente manera:

"FROM ((OTS LEFT JOIN INSTRUMENTOS ON INSTRUMENTOS.[Nº SERIE] = OTS.[Nº SERIE]) " _
            & "LEFT JOIN CERTIFICADOS ON CERTIFICADOS.[ORDEN TRABAJO] = OTS.[ORDEN TRABAJO]) " _
            & "WHERE OTS.[ORDEN TRABAJO] Like '" & "%" & cell_OT & "'"

Puedes montar algo similar adaptándolo a tus tablas y el campo por el que se relacionen.




Editado por CSharlie - 06/Abril/2015 a las 18:23
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 20:39
Hola CSharlie, gracias por contestar pero aún no me vale esa opción, o yo no he logrado entenderla. Voy a explicar de otra manera:

Supongamos solamente que sean estas dos tablas:

Esta es la SQL:

SELECT tabTrayectoriaLaboral.TrayLabCentroTrab, tabTrayectoriaLaboral.TrayLabOcupLab, tabTrayectoriaLaboral.TrayLabDesde, tabTrayectoriaLaboral.TrayLabHasta, tabTrayectoriaLaboral.TrayLabCausasDelCambio, tabTrayectoriaLaboral.TrayLabDatosPers, tabEscuelasCursadas.EscCurCurso, tabEscuelasCursadas.EscCurEscuela, tabEscuelasCursadas.EscCurFecha, tabEscuelasCursadas.EscCurDatosPers, tabEscuelasCursadas.EscCurFila

FROM tabTrayectoriaLaboral LEFT JOIN tabEscuelasCursadas ON (tabTrayectoriaLaboral.IdTrayLab = tabEscuelasCursadas.IdEscCur) AND (tabTrayectoriaLaboral.TrayLabDatosPers = tabEscuelasCursadas.EscCurDatosPers);

En este caso, si ambas tablas tienen la misma cantidad de registros ó la tabla ‘tabTrayectoriaLaboral’ tiene más registros que ‘tabEscuelasCursadas’, no hay problemas, pero si es al revés, o sea, si ‘tabEscuelasCursadas’ tiene más registros (7) que ‘tabTrayectoriaLaboral’ (6), entonces no salen los registros que están por encima, quiere decir que, el registro 7 de ‘tabEscuelasCursadas’ no se muestra. Y el problema está ahí, que la cantidad de registros de estas tablas pueden variar, lo que no puede variar por sí sola es la consulta.

No sé si logré que se me entendiera.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 20:57
Disculpen un dibujo que había puesto en el mensaje anterior:

TABLAS:       tabTrayectoriaLaboral                          tabEscuelasCursadas

CAMPOS      IdTrayLab   ---------------------------  IdEscCur

                     TrayLabCentroTrab                          EscCurCurso

                     TrayLabOcupLab                              EscCurEscuela

                     TrayLabDatosPers     -----------------   EscCurDatosPers


Saludos
Desde La Habana, Cuba
Medardo
Arriba
emiliove Ver desplegable
Moderador
Moderador


Unido: 16/Junio/2009
Localización: Mexico
Estado: Sin conexión
Puntos: 4920
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 21:28
Hola Medardo:
Yo no entiendo la SQL, puedes poner aunque sean 3 registros o cuatro de cada tabla y lo que quieres obtener.
 
Saludos.
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 22:24

Hola emiliove

Los registros que tengo son de pruebas, pero igual, para que se tenga una idea mejor:

TrayLabCentroTrab

TrayLabOcupLab

TrayLabDatosPers

EscCurCurso

EscCurEscuela

EscCurDatosPers

A100

A200

1

a4

a5

1

A400

A500

1

a6

a7

1

B1

B2

2

b9

b10

2

B4

B5

2

b9

b10

2

b6

b7

2

 

 

 

 

Esta es la SQL:

SELECT tabTrayectoriaLaboral.TrayLabCentroTrab, tabTrayectoriaLaboral.TrayLabOcupLab, tabTrayectoriaLaboral.TrayLabDatosPers, tabEscuelasCursadas.EscCurCurso, tabEscuelasCursadas.EscCurEscuela, tabEscuelasCursadas.EscCurDatosPers

FROM tabTrayectoriaLaboral LEFT JOIN tabEscuelasCursadas ON (tabTrayectoriaLaboral.IdTrayLab = tabEscuelasCursadas.IdEscCur) AND (tabTrayectoriaLaboral.TrayLabDatosPers = tabEscuelasCursadas.EscCurDatosPers);

Si te fijas, en las tres primeras columnas, que pertenecen a una tabla (tabTrayectoriaLaboral) se muestran 5 registros y, en el resto, 4 registros, que pertenecen a la tabla ‘tabEscuelasCursadas’. Es decir, la primera tabla tiene un registro más que la segunda. Hasta ahí, todo va bien. PERO,… si a la segunda tabla (tabEscuelasCursadas) se le suman 2 registros, ahora tiene 6 y cuenta con más registros que la primera; por tanto, la relación en la SQL no sirve porque mostraría la misma cantidad de registros que la primera tabla y el registro número 6 de la segunda, no se mostraría.

Ojalá me hayan entendido, jejeje.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
emiliove Ver desplegable
Moderador
Moderador


Unido: 16/Junio/2009
Localización: Mexico
Estado: Sin conexión
Puntos: 4920
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 22:35
Diras que soy un pesado, es que soy demasiado lento (torpe), pero sigo sin entender tienes 2 tablas
 

TrayLabCentroTrab

TrayLabOcupLab

TrayLabDatosPers

 

 

 

A100

A200

1

 

 

 

A400

A500

1

 

 

 

B1

B2

2

 

 

B4

B5

2

 

 

b6

b7

2

 

 
Y esta

 

 

 

EscCurCurso

EscCurEscuela

TrayLabDatosPers

 

 

 

a4

a5

1

 

 

 

a6

a7

1

 

 

 

b9

b10

2

 

 

 

b9

b10

2

 

 

 

 
la segunda con dos registros mas y que debes obtener, y cual es su relación entre las dos tablas TrayLabDatosPers y TrayLabDatosPers o cual es.
 
Saludos.
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 23:07
Hola emiliove

La relación está en el FROM de la SQL que acabo de poner en el anterior mensaje. Se relacionan por los campos IdTrayLab y IdEscCur (que no se muestran en la consulta, aunque existen) y por TrayLabDatosPers y EscCurDatosPers.

No sé si es eso lo que querías saber.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
guarracuco Ver desplegable
Moderador
Moderador
Avatar

Unido: 24/Abril/2004
Localización: EEUU
Estado: Sin conexión
Puntos: 2954
Enlace directo a este mensaje Enviado: 06/Abril/2015 a las 23:16
Por lo planteado la relacion de 1 con 2-3-4 es de uno a uno.
La relación de 1 con 5-6-7 es de uno a varios.
¿Para qué deseas una consulta en conjunto?
En un reporte o formulario puedes tener las 4 primeras como una consulta y las restantes independientes llenando respectivos subforms o subreports.
https://tucondominioaldia.net
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 07/Abril/2015 a las 21:49
Hola Guarracuco

Disculpen por no haber respondido antes, pero me encontraba en otras tareas.

Efectivamente, las relaciones son como usted dice, pero debo aclarar algo que aún no he especificado y que no lo había hecho por creerlo no necesario: mi programa no está sobre Access, sino, sobre una interface de Visual Basic 6.0, utilizando una base de datos Access 2007 para almacenar datos. Es por esta razón, que no utilizo subformularios.

Desde Visual Basic, la salva / modificación de los datos se realizan sin problema. La cuestión radica en que tengo un procedimiento personal para mostrar los datos en Microsoft Word, y esos datos sí tengo que sacarlos de una consulta. Es ahí la necesidad de que me funcione correctamente esta consulta.

Quizás esta explicación pueda hacer pensar que me equivoqué de Foro, pero cuando tengo una dificultad en base de datos, no dudo en acudir a este Foro que para mí ha sido importantísimo en mi formación como programador.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 08/Abril/2015 a las 16:03

Hola

Una pregunta:

¿Se pueden insertar en una sola instrucción sql datos de varias tablas a una tabla?

De ser posible, podrían poner un ejemplo.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 08/Abril/2015 a las 17:01

De acuerdo a una prueba que hice: Sí, es posible; por ejemplo:

"INSERT INTO TABLA1 " & _

                    "(Campo1, Campo2, " & _

                    "Campo3, Campo4, " & _

                    "Campo5, Campo6) " & _

                    "SELECT Campo1, Campo2, " & _

                    "Campo3, Campo4, " & _

                    "Campo5, Campo6 " & _

                    "FROM TABLA2, TABLA3, TABLA4"

 

TABLA1 contiene todos los campos de TABLA2, TABLA3 y TABLA4.

TABLA2 contiene los campos Campo1 y Campo2.

TABLA3 contiene los campos Campo3 y Campo4.

TABLA4 contiene los campos Campo5 y Campo6.

 

Los datos de las tablas TABLA2, TABLA3 y TABLA4 se insertan en la tabla TABLA1, pero se multiplican varias veces. ¿Alguien tiene alguna idea?

Saludos
Desde La Habana, Cuba
Medardo
Arriba
raipon Ver desplegable
Moderador
Moderador


Unido: 10/Diciembre/2004
Localización: Desconocida
Estado: Sin conexión
Puntos: 4005
Enlace directo a este mensaje Enviado: 08/Abril/2015 a las 21:25
Hola Medardo, la operación que realizas se llama cross join, y obtendrás todas las combinaciones posibles de todos los registros de las tablas que intervienen. Si en una tienes 3 registros, en otra 4 y 5 en la última, obtendrás un resultado con: 3 x 4 x 5 = 60 líneas.

Si lo que deseas es mostrar resultados de varias tablas, con una relación que sea a la vez Left Join y Right Join, esto se llama Full Join. Lamentablemente este operador no existe en Access, pero puedes emular su comportamiento con una consulta de Unión. Aquí tienes un ejemplo: http://sqlraipon.blogspot.com.es/2008/07/full-join-en-access.html

Saludos.

Editado por raipon - 08/Abril/2015 a las 21:27
Ramon desde Terrassa.

Mi blog
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 09/Abril/2015 a las 16:24
Hola raipon

 

Es un placer coincidir con usted después de tanto tiempo.

Le agradezco inmensamente su respuesta. Realmente, no tenía conocimiento que con una sola consulta se podría obtener ese resultado. En otras ocasiones, me he enfrentado a situaciones como la que expresa en su página, y he tenido que realizar varias consultas para llegar a ese resultado. De haber conocido esto antes, me hubiera ahorrado mucho tiempo.

Hice la prueba con mis datos y mejoró muchísimo el resultado, pero ahora duplica cada registro. Debería mostrar 5 registros y muestra 10, cada uno, dos veces.

No obstante, no es exactamente ese resultado que usted expone, el que yo persigo. Es bastante similar, pero no exactamente igual.

Para volverlo a explicar:

Tengo 4 tablas, una vacía con todos los campos de las restantes tres tablas, que sí tienen datos. Estas tres tablas pueden tener diferente cantidad de registros, aunque todas, van a tener un campo que hace referencia al id de una tabla principal (que en este momento no es de interés) para saber a qué persona pertenece cada uno de estos registros. Lo que pretendo es llevar los registros de estas tres tablas para la primera tabla que contiene todos los campos, pero como aquellas tienen cantidades de registros diferentes, que no sé quien tendrá más, no puedo establecer una relación definitiva. Es ahí donde está precisamente el problema. Su ejemplo, me parece que se adapta, pero no me da exactamente el resultado que deseo. Quizás necesite hacer más pruebas, quizás haya algo que no esté haciendo bien y no me he percatado, incluso la consulta no me ha dado error alguno, parece funcionar bien, pero el resultado no es el que busco.

 

Ante esta situación, he encontrado una solución a través de un procedimiento personal.

Explico desde un inicio para que pueda servir en caso que alguien se encuentre en una situación similar. No será quizás el mejor ejemplo, pero al menos fue lo que se me ocurrió (y funciona) después de llevar varios días.

 

Supongamos que queremos insertar los datos de tres tablas que tienen diferente cantidad de registros y campos, hacia una tabla.

 

Digamos que las tablas se llaman:

TABLA1 está vacía y contiene todos los campos de TABLA2, TABLA3 y TABLA4.

TABLA2 contiene los campos Campo1 y Campo2 (con registros).

TABLA3 contiene los campos Campo3 y Campo4 (con registros).

TABLA4 contiene los campos Campo5 y Campo6 (con registros).

La cantidad de registros de las tablas TABLA2, TABLA3 y TABLA4 pueden ser diferentes en cada una de ellas.

 

El ejemplo lo realizamos con dos campos en las tablas TABLA2, TABLA3 y TABLA4 para no hacerlo muy largo y sea más entendible. Aunque la cantidad de campos no importa, lo importante es que la tabla que se va a llenar (TABLA1) contenga todos los campos de las demás tablas.

 

'declaramos variables recordset de cada tabla

    Dim rstTABLA1 As New ADODB.Recordset

    Dim rstTABLA2 As New ADODB.Recordset

    Dim rstTABLA3 As New ADODB.Recordset

    Dim rstTABLA4 As New ADODB.Recordset

    'declarar variables que almacenen la cantidad de registros de cada tabla, excepto TABLA1

    Dim intTABLA2 As Integer

    Dim intTABLA3 As Integer

    Dim intTABLA4 As Integer

    'declarar variable para almacenar el mayor número de registros de las tablas

    Dim intMayorNum As Integer

    'declarar variable que se incremente en 1

    Dim intContador As Integer

   

    'verificamos si el recordset de la tabla está abierta para cerrarla y no de error al tratar de volverla a abrir

    If rstTABLA1.State = adStateOpen Then rstTABLA1.Close: Err.Clear

    'abrimos el recordset de la tabla

    rstTABLA1.Open "SELECT * FROM TABLA1 ", cnn , adOpenDynamic, adLockOptimistic

   

    If rstTABLA2.State = adStateOpen Then rstTABLA2.Close: Err.Clear

    rstTABLA2.Open "SELECT * FROM TABLA2", cnn

    'almacenamos la cantidad de registros de la tabla

    intTABLA2 = rstTABLA2.RecordCount

   

    If rstTABLA3.State = adStateOpen Then rstTABLA3.Close: Err.Clear

    rstTABLA3.Open "SELECT * FROM TABLA3", cnn

    intTABLA3 = rstTABLA3.RecordCount

   

    If rstTABLA4.State = adStateOpen Then rstTABLA4.Close: Err.Clear

    rstTABLA4.Open "SELECT * FROM TABLA4", cnn

    intTABLA4 = rstTABLA4.RecordCount

   

    'hallamos el mayor número según la tabla que mayor cantidad de registros tenga

    If (intTABLA2 > intTABLA3 And intTABLA2 > intTABLA4) Then

        intMayorNum = intTABLA2

      Else

        If (intTABLA3 > intTABLA2 And intTABLA3 > intTABLA4) Then

            intMayorNum = intTABLA3

        Else

            intMayorNum = intTABLA4

        End If

    End If

   

    'hacemos un ciclo a la tabla donde vamos a insertar los datos

    Do While rstTABLA1.EOF = False Or rstTABLA1.EOF = True

        'añadimos

        rstTABLA1.AddNew

        'aumentamos el contador

        intContador = intContador + 1

       

        'si la variable intContador es menor o igual que la cantidad de registros que tiene

        'la tabla 'TABLA2', entonces procedemos a cargar los datos para la tabla ‘TABLA1’.

        'La variable 'intContador' irá incrementándose según la tabla que tenga mayor cantidad de registros,

        'por tanto, esto es para evitar que el ciclo entre en un registro vacío (o superior al último)

        'de una tabla que tenga menos registros que la variable 'intContador'

        If intContador <= intTABLA2 Then

            rstTABLA1!Campo1 = rstTABLA2!Campo1

            rstTABLA1!Campo2= rstTABLA2!Campo2

        End If

       

        If intContador <= intTABLA3 Then

            rstTABLA1!Campo3= rstTABLA3!Campo3

            rstTABLA1!Campo4= rstTABLA3!Campo4

        End If

           

        If intContador <= intTABLA4 Then

            rstTABLA1!Campo5= rstTABLA4!Campo5

            rstTABLA1!Campo6= rstTABLA4!Campo6

        End If

       

        'si la variable intContador es menor o igual que la cantidad de registros que tiene

        'la tabla 'TABLA(n)', entonces pasamos al siguiente registro.

        'De no especificar esta condición, se entraría a un registro superior al último, que no existe,

        'y se produciría un error

        If intContador <= intTABLA2 Then rstTABLA2.MoveNext

        If intContador <= intTABLA3 Then rstTABLA3.MoveNext

        If intContador <= intTABLA4 Then rstTABLA4.MoveNext

       

        'actualizamos todos los datos en un mismo registro de la tabla ‘TABLA1’

        rstTABLA1.Update

       

        'si la variable 'intContador' ya es igual al mayor número de registros posibles a insertar

        'entonces, salimos del ciclo

        If intContador = intMayorNum Then Exit Do

    Loop

   

    'cerrar recordset

    rstTABLA1.Close

    'eliminar los objetos o liberarlos de la memoria

    Set rstTABLA1= Nothing

   

    rstTABLA2.Close

    Set rstTABLA2= Nothing

   

    rstTABLA3.Close

    Set rstTABLA3= Nothing

   

    rstTABLA4.Close

    Set rstTABLA4= Nothing

 

Por mi parte, si no hay más que aportar, pueden cerrar el hilo.

Gracias a todos.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
 Responder Responder
  Compartir tema   

Ir al foro Permisos de foro Ver desplegable