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

Varias filas o varias columnas para una tabla

Estas en el tema de Varias filas o varias columnas para una tabla en el foro de Bases de Datos General en Foros del Web. Buenas, se que ya habrán tratado este tema pero queria escuchar conceptos mas precisos: Los usuarios de una tabla pueden querer enseñar 3 idiomas y ...
  #1 (permalink)  
Antiguo 21/05/2008, 17:21
Avatar de mafima  
Fecha de Ingreso: abril-2003
Ubicación: Medellin-Colombia
Mensajes: 1.109
Antigüedad: 21 años
Puntos: 24
Varias filas o varias columnas para una tabla

Buenas, se que ya habrán tratado este tema pero queria escuchar conceptos mas precisos:

Los usuarios de una tabla pueden querer enseñar 3 idiomas y aprender 3 idiomas ( me refiero a entre uno y 3)

mi rpegunta es, que estructura es mejor:

1.

[tabla_usuarios]
ID_usuario
nombre
email
idioma_ensenta1
idioma_ensenta2
idioma_ensenta3
idioma_aprende1
idioma_aprende2
idioma_aprende3

o

2.
[tabla_usuarios]
ID_usuario
nombre
email

[tabla_ensena]
ID_usuario
idioma_ensena

[tabla_aprende]
ID_usuario
idioma_aprende

en el segundo caso tendria que hacer relaciones, la cosa es que se me complican muchos las consultas y no se si merece la pena, ya que estoy seguro que solamente los usuarios pueden querer enseñar y aprender 3 idiomas.

si escogiera el segundo caso como seria una consulta que haga lo siguiente:
seleccionar los usuarios que quieren aprender el idioma español, y luego mostrar además de ese idioma que otros idioma desean aprender. ( sin usar subconsultas )

muchas gracias
__________________
SEO en Medellin
  #2 (permalink)  
Antiguo 22/05/2008, 02:00
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Varias filas o varias columnas para una tabla

Si no vas a aumentar nunca el numero de idiomas por usuario puedes hacerlo con la primera pero como te aparezca un usuario que quiere 4 o quieras que tu empresa crezca y dejar libre el numero de idiomas vas a tener problemas... (en si es un error de diseño)

Tanto en el primer caso como en el segundo te faltaria una tabla:

TablaIdiomas
idIdioma
nombreidioma


y en las tablas usuario, ensena i aprende guardas el id del idioma no el nombre, esto reducirá mucho el espacio en disco y elimina la posibilidad de escribir el nombre de un idioma de distintas formas "Español" "Castellano"....

la consulta que pides no se me ocurre como hacerla sin subconsultas....

Código:
Select tabla_usuarios.nombre,
          tabla_aprende.idioma_aprende
from tabla_usuarios inner join tabla_aprende
        on tabla_usuarios.ID_usuario= tabla_aprende.ID_usuario
where tabla_usuarios.ID_usuario 
               in (Select tabla_usuarios.ID_usuario
                         from tabla_usuarios inner join tabla_aprende
                         on tabla_usuarios.ID_usuario= tabla_aprende.ID_usuario
                         where idioma_aprende="Español");
Quim
  #3 (permalink)  
Antiguo 22/05/2008, 03:24
 
Fecha de Ingreso: enero-2007
Mensajes: 38
Antigüedad: 17 años, 3 meses
Puntos: 0
Respuesta: Varias filas o varias columnas para una tabla

Sin duda la segunda opcion es mucho mas eficiente. En la primera tendras los datos de los usuarios a veces hasta triplicados, y no es nada bueno, hay que evitar las redundancias. Evidentemente tendrias que añadir la Tabla TablaIdiomas como bien dice Quimfv, para quitar las redundancias totalmente.
  #4 (permalink)  
Antiguo 22/05/2008, 10:58
Avatar de mafima  
Fecha de Ingreso: abril-2003
Ubicación: Medellin-Colombia
Mensajes: 1.109
Antigüedad: 21 años
Puntos: 24
Respuesta: Varias filas o varias columnas para una tabla

Hola gracias por sus prontas respuestas,

Queria que me explicaran porque dicen que seran datos redundantes?

pues si nos fijamos solo habrá un usuario por fila y este usuario solo va a querer aprender y enseñar 3 idiomas diferentes.

PD: estoy seguro que nunca vamos a permitir mas de tres idiomas para enseñar y 3 idiomas para aprender.

Lo que pasa es que me parece muy poco eficiente ( aunque hablo desde mi ignorancia ) por ejemplo en el segundo caso si quiero sacar una relacion de que idiomas quiere aprender cada usuario su nombre y su email, tendira que tener una consulta asi:

Código:
select tabla_usuarios.email, tabla_usuarios.nombre, GROUP_CONTACT(tabla_ensena.idioma_ensena) AS ensena, GROUP_CONTACT(tabla_aprende.idioma_aprende) AS aprende from tabla_usuarios INNER JOIN tabla_ensena ON tabla_usuarios.ID_usuario=tabla_ensena.ID_usuario INNER JOIN tabla_aprende ON tabla_usuarios.ID_usuario=tabla_arende.ID_usuario GROUP BY ID_usuario
mientras que si lo tengo de la primera forma la consulta seria:

select * from tabla_usuarios

Me da la impresion que la segunda cunsulta puede ser mas optima y rapida que la primera, ustedes que creen?
__________________
SEO en Medellin
  #5 (permalink)  
Antiguo 22/05/2008, 11:25
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Varias filas o varias columnas para una tabla

mafima,
es cierto lo que dices, pero yo estoy con quimfv.
Te haré unas preguntas para que veas la índole del problema:
¿Cómo buscarías todos los que quieren estudiar inglés?
¿Cómo buscarías el total de los alumnos que quieren estudiar dos lenguas y que esas sean unas determinadas?
Observarás que ahora tienes que buscar en los distintos campos de un registro sin saber dónde está la lengua que buscas, si en el primer campo, en el segundo o en el tercero. Eso también ralentizará tus consultas, pues incluso optimizándolas, tendrás que mover muchos datos y los índices no te ayudarán como si tuvieras los registros con una lengua cada uno de ellos; y tendrás que volver varias veces sobre la misma tabla: si buscas, tres, tres veces, recorriendo los tres campos. Y si el problema es la presentación de los datos en columnas, eso se resuelve con programación. Ni siquiera tienes que hacer un concat, sino programar con PHP, ASP o lo que emplees...

Última edición por jurena; 22/05/2008 a las 11:51
  #6 (permalink)  
Antiguo 22/05/2008, 12:31
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Varias filas o varias columnas para una tabla

El tema de la redundancia solo se daria si no creas la tabla que te comente que te evitará guardar el nombre de los idiomas n veces.

No se da con los datos del usuario puesto que solo los tendrias una vez junto con sus seis idiomas relacionados...

Ahora que me lo miro la consulta que te pase con subconsultas puede ser un poco mas simple...

Código:
Select tabla_usuarios.nombre,
          tabla_aprende.idioma_aprende
from tabla_usuarios inner join tabla_aprende
        on tabla_usuarios.ID_usuario= tabla_aprende.ID_usuario
where tabla_usuarios.ID_usuario 
               in (Select tabla_aprende.ID_usuario
                         from tabla_aprende
                         where idioma_aprende="Español");
Dicho esto, lee con atención a jurema e intenta formular las sentencias para las preguntas que te ha planteado en los dos modelos.

Piensa que el tiempo que pierdas pensando una sentencia complicada solo se pierde una vez y al contrario el tiempo de cpu que se pierda por un mal modelo se perderá tantas veces como se ejecute la sentencia, si haces la suma de tiempos ya me dirás que es mejor...

Ademas cada vez que piensas una sentencia aprendes un poco mas con lo que la siguiente te saldrá más facil, encambio la cpu siempre ejecuta las cosas al mismo ritmo... ufff alta filosofia .

Quim
  #7 (permalink)  
Antiguo 22/05/2008, 14:03
Avatar de mafima  
Fecha de Ingreso: abril-2003
Ubicación: Medellin-Colombia
Mensajes: 1.109
Antigüedad: 21 años
Puntos: 24
Respuesta: Varias filas o varias columnas para una tabla

Bueno, ustedes tienen razón lo mejor entonces tener aislados.

para las consultas que me preguntaron seria:

primer consulta
select * from tabla_usuarios WHERE idioma_aprende1=1 OR idioma_aprende2=1 ORidioma_aprende3=1

select * from tabla_usuarios WHERE idioma_aprende1=1 OR idioma_aprende2=1 OR idioma_aprende3=1 OR idioma_aprende1=2 OR idioma_aprende2=2 OR idioma_aprende3=2

las consultas en realidad son muy simples y podria hacer dos indices multiples: donde ponga en el primero: idioma_aprende1,idioma_aprende2,idioma_aprende3
y en el segundo: idioma_ensena1,idioma_ensena2,idioma_ensena3

Sin embargo no se si sea igual de óptimo.
Otra cosa que veo es que en parte mis consultas se lian porque pienso en la forma en que voy paginar los resultaso y a mostrarlos quizas sea mas optimo no hacer el contact con mysql sino directamente con PHP como dice jurena.

entonces como conclusion podriamos decir que es mejor usar el 2 metodo paa realizar la estructura de mis tablas aun cuando no las piense expandir en un futuro?

PD: MIl y mil gracias, la verdad es que me es muy útil la información que me proporc ionan.
__________________
SEO en Medellin
  #8 (permalink)  
Antiguo 22/05/2008, 15:37
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Varias filas o varias columnas para una tabla

Y ahora, mafima, una pregunta con trampa:
¿cómo sacarías el idioma más estudiado?
¿por qué campo de los tres agruparías para sacar el MAX() ... group by, pues no puedes agrupar por los tres a la vez...?
A estas cosas me refiero.
  #9 (permalink)  
Antiguo 22/05/2008, 17:10
Avatar de mafima  
Fecha de Ingreso: abril-2003
Ubicación: Medellin-Colombia
Mensajes: 1.109
Antigüedad: 21 años
Puntos: 24
Respuesta: Varias filas o varias columnas para una tabla

jeje, es cierto.
lo unico seria examinarlo por columnas y luego sumar con PHP u otro lenguaje

de cualquier forma seguro que si lo hago asi los estaré molestando mucho para ue me ayuden a armar consultas o examinen las que ya tengos.

Por cierto, aprovecho para preguntarles: hay alguna forma de saber cuanto tiempo le tomo al MYSQL ejecutar una consulta?
__________________
SEO en Medellin
  #10 (permalink)  
Antiguo 23/05/2008, 00:56
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Varias filas o varias columnas para una tabla

Que yo sepa, si lanzas la consulta en la ventana SQL de PHPMyAdmin, el programa te ofrece esa información. Otra opción sería hacerlo con programación. En PHP se usa para eso la función microtime(). Mira el manual y pregunta en el foro PHP.
http://es2.php.net/microtime
  #11 (permalink)  
Antiguo 23/05/2008, 01:11
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Varias filas o varias columnas para una tabla

Vas a entrar en el bonito mundo de la optimización de bbdd....

12.3.2. EXPLAIN Syntax


Con explain plan puedes optimizar tus consultas, puesto que te muestra que hace el motor para obtener el resultado pedido, si usa indices, si no los usa si recorre mas de una vez alguna tabla....

La mayoria de sentencias de un cierto nivel de complicación se pueden formular de varias formas para obtener el mismo resultado esto te mostrará cual es mas eficiente....

Este tema lo estudie sobre Oracle por lo que no estoy seguro si existen las mismas opciones, pero podias conseguir reducciones del orden de 600 a 6 en tiempo de cpu segun como formules la sentencia....

A, y pregunta lo que quieras como mas complicado mejor que como sabe jurema las preguntas mas complicadas son las que incentivan mas a intentar dar una respuesta.

Por otro lado, tampoco te obsesiones si no estas trabajando con grandes cantidades de registros, como mas eficiente mejor pero todo a su medida...

Quim
  #12 (permalink)  
Antiguo 23/05/2008, 04:44
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Varias filas o varias columnas para una tabla

Yo, la verdad, me quedé algo (al menos un poco) decepcionado con el EXPLAIN EXTENDED aplicado a consultas de MysQL, sobre todo después de ver la información entregada por ORACLE a una consulta de este tipo que nos mostró matanga en otro post.
En MySQL, que yo haya visto, nada de tiempo ni de porcentajes de utilización de la CPU al hacer la consulta con Explain: en fin, imagino que las sucesivas versiones mejorarán este punto, si no lo han hecho ya (yo utilizo MySQL 5.0.1).
Creo que para lo del tiempo tendrás que lanzar las consultas en PHPMyAdmin o más fácil, crear una función PHP para medir el tiempo de tus consultas. En el manual de PHP hay algún ejemplo al hablar de microtime(). De todas formas, puedes pedir ayuda en el foro PHP.
Ah, mafima, no conozco todavía mucho a la gente del foro, pero tan pronto como tengas necesidad de alguna aclaración sobre una consulta de MySQL que requiera subconsultas, agrupaciones, etc., estoy seguro de que, entre muchos otros, estará nuestro Quim (permítemelo, Quim) comenzando a hacer pruebas en casa: lo sé por experiencia y no porque me lo hayan contado.

Última edición por jurena; 23/05/2008 a las 07:33
  #13 (permalink)  
Antiguo 23/05/2008, 04:59
 
Fecha de Ingreso: enero-2007
Mensajes: 38
Antigüedad: 17 años, 3 meses
Puntos: 0
Respuesta: Varias filas o varias columnas para una tabla

en mi opinion lo mas correcto seria lo siguiente:

TABLA1(id_usuario,nombre_usuario,email)
TABLA2(id_idioma,nombre_idioma)
TABLA3(id_usuario,id_idioma,modo[aprende || enseña] )
  #14 (permalink)  
Antiguo 23/05/2008, 07:07
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Varias filas o varias columnas para una tabla

Par mi tambien, pero pon nombre a las tablas y el modo que sea 1 o 0 que ocupa menos...

... hay quien tira flores, pero tambien sabe mucho.... Gracias de todos modos.


Quim
  #15 (permalink)  
Antiguo 23/05/2008, 07:53
Avatar de mafima  
Fecha de Ingreso: abril-2003
Ubicación: Medellin-Colombia
Mensajes: 1.109
Antigüedad: 21 años
Puntos: 24
Respuesta: Varias filas o varias columnas para una tabla

Hola, de nuevo gracias por sus palabras de aliento.

Entonces resulta que la forma más optima sería:

Código:
tabla_usuarios(id_usuario,nombre_usuario,email)
tabla_idioma(id_idioma,nombre_idioma)
tabla_idioma_usuarios(id_usuario,id_idioma,modo[1 || 2] )

Con esa estructura, ¿cómo sería la siguiente consulta?

- Necesito sacar el nombre y el mail y los idiomas que quieren aprender y los idiomas que quieren enseñar todos los usuarios que quieren aprender inglés ( id_idioma =1 )

Agradezco mucho su atención.

Hasta luego.
__________________
SEO en Medellin
  #16 (permalink)  
Antiguo 23/05/2008, 09:58
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Varias filas o varias columnas para una tabla

Encantado pero ahora no nos vas a pedir todas las consultas no?

Cita:
- Necesito sacar el nombre y el mail y los idiomas que quieren aprender y los idiomas que quieren enseñar todos los usuarios que quieren aprender inglés ( id_idioma =1 )

aprender --> modo=1

Código:
SELECT tabla_usuarios.id_usuario, 
             tabla_usuarios.nombre_usuario, 
             tabla_usuarios.email, 
             tabla_idioma.nombre_idioma, 
             tabla_idioma_usuarios.modo
FROM (tabla_usuarios LEFT JOIN tabla_idioma_usuarios 
                         ON tabla_usuarios.id_usuario = tabla_idioma_usuarios.id_usuario)
                      LEFT JOIN tabla_idioma 
                         ON tabla_idioma_usuarios.id_idioma = tabla_idioma.id_idioma
WHERE tabla_usuarios.id_usuario 
          In (SELECT tabla_usuarios.id_usuario,
               FROM tabla_usuarios 
                    LEFT JOIN tabla_idioma_usuarios
                       ON tabla_usuarios.id_usuario = tabla_idioma_usuarios.id_usuario
               WHERE tabla_idioma_usuarios.id_idioma=1 
                                AND tabla_idioma_usuarios.modo=1)
ORDER BY tabla_usuarios.nombre_usuario,
         tabla_idioma_usuarios.modo,
         tabla_idioma.nombre_idioma;
Comentario, tengo que obtener los usuarios que aprenden ingles, consulta facil ( where id_idioma=1), una vez tengo estos solo tengo que obtener el resto de idiomas que quieren aprender o enseñar.

Quim
  #17 (permalink)  
Antiguo 23/05/2008, 10:30
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Varias filas o varias columnas para una tabla

Con GROUP_CONCAT
enseñar: modo=0
aprender: modo =1
inglés: id_idioma = 1


SELECT distinct tu.nombre_usuario, tu.email, TRIM(group_concat (distinct if(tiu.modo=0, ti.nombre_idioma, "") ORDER BY ti.nombre_idioma ASC SEPARATOR ' ')) as aprender, TRIM(group_concat(distinct if(tiu.modo = 1, ti.nombre_idioma, "") ORDER BY ti.nombre_idioma SEPARATOR ' ')) as enseñar FROM tabla_usuarios tu INNER JOIN tabla_idioma_usuarios tiu ON tu.id_usuario = tiu.id_usuario INNER JOIN tabla_idioma ti ON ti.id_idioma = tiu.id_idioma where tu.id_usuario IN (select tu.id_usuario FROM tabla_usuarios tu INNER JOIN tabla_idioma_usuarios tiu ON tu.id_usuario = tiu.id_usuario INNER JOIN tabla_idioma ti ON ti.id_idioma = tiu.id_idioma WHERE tiu.id_idioma = 1 AND tiu.modo = 0) group by tu.id_usuario

He añadido TRIM para quitar los espacios en blanco al principio y final del GROUP_CONCAT. Ahora con espacio por medio entre los idiomas será fácil manejarlo con PHP...

Última edición por jurena; 23/05/2008 a las 10:57 Razón: añadir dos TRIM() y alguna aclaración
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 11:48.