Foro de elhacker.net

Programación => Bases de Datos => Mensaje iniciado por: mark182 en 22 Noviembre 2009, 10:30 am



Título: Se puede hacer esto?
Publicado por: mark182 en 22 Noviembre 2009, 10:30 am
Buenas..como estan?

Estoy haciendo algo parecido a un libro de visitas pero que el administrador de la web pueda responder a los mensajes. Entonces lo que quiero saber como puedo hacer para que, en la misma tabla donde se guardan las preguntas y/o comentarios, tambien se guarden las respuestas a dicha pregunta. Les muestro las tabla que tengo en la base de datos:

+----------+
|preguntas|
+----------+
| id_preg |
| nombre |
| apellido |
| mensaje|
|respuestas|
+----------+

El usuario escribe su nombre, apellido y el mensaje y eso queda guardado en esta tabla y se muestra en la pagina. Lo que quiero hacer es que el administrador de la web le escriba la respuesta a dicha persona y eso se inserte en esta tabla en el registro "respuestas" segun a al nombre y apellido que le responda (osea la persona que hizo la pregunta). Me explico?

Desde ya muchas gracias.


Título: Re: Se puede hacer esto?
Publicado por: MasterPunk en 22 Noviembre 2009, 10:45 am
yo no pondria mi apellido xD


Título: Re: Se puede hacer esto?
Publicado por: braulio-- en 22 Noviembre 2009, 10:49 am
Claro que se puede hacer, si cada pregunta/comentario tiene un id específico solo tienes que hacer un :
Código:
UPDATE librovisitas SET respuesta='$respuesta' WHERE id_preg=$id


Título: Re: Se puede hacer esto?
Publicado por: Carlosnuel en 22 Noviembre 2009, 19:38 pm
Claro que se puede hacer, si cada pregunta/comentario tiene un id específico solo tienes que hacer un :
Código:
UPDATE librovisitas SET respuesta='$respuesta' WHERE id_preg=$id


Pero que pasaría si hubieran 5 respuestas a 1 pregunta. Solamente se mostraria la 5° respuesta.
Lo que recomiendo es hacer una tabla intermedia entre respuestas y preguntas

Tabla preguntas
-  idpregunta
- nombre
- fecha
- pregunta

Tabla Pregunta_respuesta
- idpregunta
- idrespuesta

Tabla Respuesta
- idrespuesta
- nombre
- fecha
-respuesta

Con esto 1 pregunta pudiera tener 5 o más respuestas


Título: Re: Se puede hacer esto?
Publicado por: mark182 en 22 Noviembre 2009, 19:52 pm

Pero que pasaría si hubieran 5 respuestas a 1 pregunta. Solamente se mostraria la 5° respuesta.
Lo que recomiendo es hacer una tabla intermedia entre respuestas y preguntas

Tabla preguntas
-  idpregunta
- nombre
- fecha
- pregunta

Tabla Pregunta_respuesta
- idpregunta
- idrespuesta

Tabla Respuesta
- idrespuesta
- nombre
- fecha
-respuesta

Con esto 1 pregunta pudiera tener 5 o más respuestas

Y que se relacionaria con que? o como seria el codigo sql para hacer la consulta?


Título: Re: Se puede hacer esto?
Publicado por: Kasi en 23 Noviembre 2009, 16:24 pm
Algo similar a:
Código:
SELECT lo que sea
FROM (Preguntas
INNER JOIN Pregunta_Respuesta ON Preguntas.idpregunta = Pregunta_respuesta.idpregunta)
INNER JOIN Respuesta ON Respuesta.idrespuesta = Pregunta_Respuesta.idrespuesta

No es recomendable que hagas la select con el * puesto que te devuelve todos los campos de las 3 tablas, obtén únicamente los necesarios(imagínate sino con tablas grandes :P )


Título: Re: Se puede hacer esto?
Publicado por: Nakp en 23 Noviembre 2009, 16:32 pm
ehm... yo crearía una nueva tabla y la relacionaría con las preguntas... cuestión de diseño :rolleyes:

como ya te respondieron... se puede, pero no se debe xD

por cierto, solo serían 2 tablas

Preguntas
Respuestas
idpregunta
pregunta
fecha
iduser (fk)
idrespuesta
respuesta
fecha
iduser(fk)
idpregunta(fk)
y la relación:

pregunta |------< respuestas (1 - n)

la tabla que puso carlosnuel sobra xD




Título: Re: Se puede hacer esto?
Publicado por: ^Tifa^ en 23 Noviembre 2009, 16:56 pm
Esto deberia ir en el foro de Base de Datos no de PHP como tal  :-*

Me gusta mas el modelado de Carlosnuel (Es que es el modelado antiguo  ;D  y aun funciona) Es cierto 1 pregunta puede tener mas de 1 respuesta, por ende me atrae mas la idea de enlazar esto con una tercera tabla y 2 indices. Ya que si uso fk estas no se pueden repetir...

Aunque al modelado si le cortaria algunos campos para que no se repitan:

Tabla preguntas
- idpregunta
- nombre
- fecha
- pregunta

Tabla Pregunta_respuesta
- index( idpregunta, idrespuesta)

Tabla Respuesta
- idrespuesta
- respuesta

Es solo mi humilde opinion  :P


Título: Re: Se puede hacer esto?
Publicado por: Nakp en 23 Noviembre 2009, 17:04 pm
el modelo de carlos nuel es para n-n xD 1 pregunta varias respuestas, 1 respuesta a varias preguntas????? y... las fk se pueden repetir no? las pk no! xD


Título: Re: Se puede hacer esto?
Publicado por: ^Tifa^ en 23 Noviembre 2009, 17:14 pm
Precisamente cielo, como las fk no se pueden repetir en que punto van a concordar mi

idpregunta de las tablas Preguntas con idpregunta de la tabla respuesta? No pueden ser iguales, por ende si yo tuviera lo siguiente:

idpregunta       texto
     1               pregunta 'de que color es el sol'

idpregunta        texto
       1             respuesta : Amarillo
       2             respuesta : blanco

La misma pregunta pero no puedo enlazar las mismas respuestas por su valor que no puede repetirse, a no ser claro, que uses una tercera tabla de relacion de 2 indices. Que con fk hasta lo que me concierne no se puede. Hay situaciones donde fk si es efectivo pero hay otras donde bueno... no aplicaria.

Ahora lo anterior con el modelado de CarlosNuel

idpregunta       texto
     1               pregunta 'de que color es el sol'

idpregunta        texto
       1             respuesta : Amarillo
       1             respuesta : blanco

Misma pregunta y sus mismas respuestas.


Título: Re: Se puede hacer esto?
Publicado por: Nakp en 23 Noviembre 2009, 17:38 pm
pues hasta donde entiendo, la clave foránea debe ser única en la tabla referenciada, donde es primaria, así se pueden relacionar varios registros de la tabla donde es foránea, con 1 donde es primaria...

Preguntas
ID_Preguntas(pk)
Texto
1
como estan?
2
cual es tu nick?
Respuestas
ID_Respuestas(pk)
ID_Preguntas(fk)
Texto
1
1
bien, gracias :P
2
1
no tan bien...
3
1
situación suicida xD
4
2
mi nick es Nakp
5
2
mi nick es...
ahora... si no me equivoco cada que haces esto automaticamente se crea la tabla de indices?


Título: Re: Se puede hacer esto?
Publicado por: ^Tifa^ en 23 Noviembre 2009, 17:52 pm
Ok.. aplicando lo que acabas de mostrar (Si es que entendi correctamente).

ID_Preguntas(fk)  No es una llave primaria ni una llave unique. Porque si lo fuese no acceptara los valores repetidos que expones en tu ejemplo. Asumire que ID_Preguntas(fk) es un INDEX de lo contrario no puedes colocar valores repetidos, por esa razon es que hasta ahora me ha gustado mas el modelado de CarlosNuel  :-* (No te sientas celoso Napk no tengo nada contra tu modelado) hasta ahi estamos de acuerdo.

 
Citar
ahora... si no me equivoco cada que haces esto automaticamente se crea la tabla de indices?

Ese punto no lo he entendido muy claro, se genera automaticamente si el motor en este caso MySQL lleva auto_increment o si es otro motor como Oracle pues con sequence... o sino te referias a esto, podrias exponerlo mejor porque no entiendo.


Título: Re: Se puede hacer esto?
Publicado por: Nakp en 23 Noviembre 2009, 18:07 pm
eso... no es unique ni pk xD... es pk en la tabla referenciada (en este caso, la tabla preguntas), y si, es un index

sobre los indices... ni yo lo tengo claro jaja asi que no hagas caso :P pero no, no me refiero a eso xD


Título: Re: Se puede hacer esto?
Publicado por: ^Tifa^ en 23 Noviembre 2009, 18:19 pm
Ahhhhhhhh ok ahora si aplica el ejemplo dado por ti  ;D

Solo si el campo ID_Preguntas(fk) es un INDEX o KEY (En MySQL ya que estos dos no existen en todos los motores).

INDEX o KEY son indices ordinarios, digase acceptan nulos no tienen restricciones de repeticion de valores, por ende son ideales para este caso. El modelado de CarlosNuel es lo mismo como si usases INDEX o KEY en tablas como tu ejemplo, a diferencia que hay que crear una tercera tabla (para mi visualmente estetico mas bonito y organizado  :-* )


Título: Re: Se puede hacer esto?
Publicado por: ^Tifa^ en 24 Noviembre 2009, 01:20 am
Hola.

A todo esto no te hemos colocado un simple ejemplo que te podria servir de guia en todo lo que hemos expuesto. Lo siguiente es sencillo, pero podria servirte como una guia basica de por donde empezar para completar tus ideas. Supongo que tu peticion es que X usuario genere una pregunta donde solo el Administrador y el usuario que genero la pregunta puedan responder a la dichosa pregunta del libro de visitas.

Supondre que estas trabajando bajo una base de datos MySQL. Y utilizare el modelado antiguo expuesto por CarlosNuel (Es que me encantan  ;D)

Tengo de ejemplo estas 3 tablas:

Código
  1.  
  2. mysql> SHOW TABLES;
  3. +--------------------+
  4. | Tables_in_primaria |
  5. +--------------------+
  6. | Libro              |
  7. | Respuesta          |
  8. | Usuarios           |
  9. +--------------------+
  10. 3 ROWS IN SET (0.00 sec)
  11.  
  12.  

La tabla Usuarios validara que usuario genero que pregunta y en base a ello le permitira responder en su propia pregunta o no... (dicha validacion ya te tocara hacerle dentro del codigo PHP)

Los campos de cada una son:

Código
  1.  
  2. mysql> EXPLAIN Libro;
  3. +----------+------------+------+-----+---------+----------------+
  4. | FIELD    | TYPE       | NULL | KEY | DEFAULT | Extra          |
  5. +----------+------------+------+-----+---------+----------------+
  6. | id_libro | tinyint(4) | NO   | PRI | NULL    | AUTO_INCREMENT |
  7. | titulo   | CHAR(20)   | YES  |     | NULL    |                |
  8. | pregunta | CHAR(40)   | YES  |     | NULL    |                |
  9. +----------+------------+------+-----+---------+----------------+
  10. 3 ROWS IN SET (0.00 sec)
  11.  
  12. mysql> EXPLAIN Respuesta;
  13. +------------+------------+------+-----+---------+-------+
  14. | FIELD      | TYPE       | NULL | KEY | DEFAULT | Extra |
  15. +------------+------------+------+-----+---------+-------+
  16. | id_usuario | tinyint(4) | YES  | MUL | NULL    |       |
  17. | id_res     | tinyint(4) | YES  |     | NULL    |       |
  18. | respuesta  | CHAR(100)  | YES  |     | NULL    |       |
  19. +------------+------------+------+-----+---------+-------+
  20. 3 ROWS IN SET (0.00 sec)
  21.  
  22. mysql> EXPLAIN Usuarios;
  23. +------------+-------------+------+-----+---------+----------------+
  24. | FIELD      | TYPE        | NULL | KEY | DEFAULT | Extra          |
  25. +------------+-------------+------+-----+---------+----------------+
  26. | id_usuario | tinyint(4)  | NO   | PRI | NULL    | AUTO_INCREMENT |
  27. | usuario    | CHAR(10)    | YES  |     | NULL    |                |
  28. | contrasena | VARCHAR(50) | YES  |     | NULL    |                |
  29. +------------+-------------+------+-----+---------+----------------+
  30. 3 ROWS IN SET (0.00 sec)
  31.  
  32.  

PD: Lo anterior son tablas creadas como ejemplo, recuerda no crear campos que accepten valores nulos para no desviarte de la normalizacion  ;)

Ahora suponte que la tabla Usuarios tiene ya 3 usuarios con contrasena registrados.

Código
  1.  
  2. mysql> SELECT * FROM Usuarios;
  3. +------------+---------+----------------------------------+
  4. | id_usuario | usuario | contrasena                       |
  5. +------------+---------+----------------------------------+
  6. |          1 | coco    | 202cb962ac59075b964b07152d234b70 |
  7. |          2 | maria   | 202cb962ac59075b964b07152d234b70 |
  8. |          3 | pedro   | 202cb962ac59075b964b07152d234b70 |
  9. +------------+---------+----------------------------------+
  10. 3 ROWS IN SET (0.00 sec)
  11.  
  12.  

Las contrasenas estan encriptadas en md5 por eso se ven de esa manera.

Ahora imagina que los 3 usuarios existentes ya realizaron 1 pregunta en el libro de visitas.

Código
  1.  
  2. mysql> SELECT * FROM Libro;
  3. +----------+--------------------+---------------------------------+
  4. | id_libro | titulo             | pregunta                        |
  5. +----------+--------------------+---------------------------------+
  6. |        1 | Como es el Sol?    | Quisiera saber porque es blanco |
  7. |        2 | Como es la lluvia? | Porque es transparente          |
  8. |        3 | Juego Favorito     | Cual me recomiendan             |
  9. +----------+--------------------+---------------------------------+
  10. 3 ROWS IN SET (0.00 sec)
  11.  
  12.  

PD: En el caso anterior al campo id_libro ser una clave primaria dicho usuario solo podra tener capacidad de generar 1 sola pregunta ninguna mas eternamente. Ya que el campo id_libro tiene el mismo valor que id_usuario de Usuarios, pero aunque reconozco esta limitacion esto solo es un ejemplo de guia y en la tabla siguiente te podria dar una idea mas clara de como trabajar con doble indices (un primario y secundario) para que dicho usuario pueda regresar a generar un tema nuevo  ;)

Ahora se insertan varios datos segun la pregunta solicitada.

Código
  1. mysql> INSERT INTO Respuesta VALUES((SELECT id_usuario FROM Usuarios WHERE usuario = 'coco'), (SELECT id_usuario FROM Usuarios WHERE usuario = 'coco'), 'Es blanco por su iluminacion interna');                                                                                                  
  2. Query OK, 1 ROW affected (0.00 sec)                                                                                                              
  3.  
  4. mysql> INSERT INTO Respuesta VALUES((SELECT id_usuario FROM Usuarios WHERE usuario = 'coco'), (SELECT id_usuario FROM Usuarios WHERE usuario = 'coco'), 'Entonces porque cambia a amarillo');
  5. Query OK, 1 ROW affected (0.00 sec)        
  6.  
  7. mysql> INSERT INTO Respuesta VALUES((SELECT id_usuario FROM Usuarios WHERE usuario = 'coco'), (SELECT id_usuario FROM Usuarios WHERE usuario = 'coco'), 'por efecto de alejacion');
  8. Query OK, 1 ROW affected (0.00 sec)
  9.  
  10. mysql> INSERT INTO Respuesta VALUES((SELECT id_usuario FROM Usuarios WHERE usuario = 'maria'), (SELECT id_usuario FROM Usuarios WHERE usuario = 'maria'), 'por la gravedad');
  11. Query OK, 1 ROW affected (0.00 sec)
  12.  
  13. mysql> INSERT INTO Respuesta VALUES((SELECT id_usuario FROM Usuarios WHERE usuario = 'maria'), (SELECT id_usuario FROM Usuarios WHERE usuario = 'maria'), 'Por la densidad');
  14. Query OK, 1 ROW affected (0.00 sec)
  15.  

Quedando en un total asi:

Código
  1.  
  2. mysql> SELECT * FROM Respuesta;                                                                                                                  +------------+--------+--------------------------------------+
  3. | id_usuario | id_res | respuesta                            |
  4. +------------+--------+--------------------------------------+
  5. |          1 |      1 | Es blanco por su iluminacion interna |
  6. |          1 |      1 | Entonces porque cambia a amarillo    |
  7. |          1 |      1 | por efecto de alejacion              |
  8. |          2 |      2 | por la gravedad                      |
  9. |          2 |      2 | Por la densidad                      |
  10. +------------+--------+--------------------------------------+
  11. 5 ROWS IN SET (0.00 sec)
  12.  
  13. mysql> SELECT * FROM Respuesta WHERE id_usuario = ( SELECT id_usuario FROM Usuarios WHERE usuario = 'coco');
  14. +------------+--------+--------------------------------------+
  15. | id_usuario | id_res | respuesta                            |
  16. +------------+--------+--------------------------------------+
  17. |          1 |      1 | Es blanco por su iluminacion interna |
  18. |          1 |      1 | Entonces porque cambia a amarillo    |
  19. |          1 |      1 | por efecto de alejacion              |
  20. +------------+--------+--------------------------------------+
  21. 3 ROWS IN SET (0.00 sec)
  22.  
  23. mysql> SELECT * FROM Respuesta WHERE id_usuario = ( SELECT id_usuario FROM Usuarios WHERE usuario = 'maria');
  24. +------------+--------+-----------------+
  25. | id_usuario | id_res | respuesta       |
  26. +------------+--------+-----------------+
  27. |          2 |      2 | por la gravedad |
  28. |          2 |      2 | Por la densidad |
  29. +------------+--------+-----------------+
  30. 2 ROWS IN SET (0.00 sec)
  31.  
  32.  

PD: Por optimizacion los campos 'usuario' de la tabla Usuarios deberian asignarseles un index para aprovechar la rapidez de consultas:

Código
  1.  
  2. mysql> EXPLAIN SELECT * FROM Respuesta WHERE id_usuario = ( SELECT id_usuario FROM Usuarios WHERE usuario = 'maria');
  3. +----+-------------+-----------+------+---------------+------------+---------+-------+------+-------------+
  4. | id | select_type | TABLE     | TYPE | possible_keys | KEY        | key_len | REF   | ROWS | Extra       |
  5. +----+-------------+-----------+------+---------------+------------+---------+-------+------+-------------+
  6. |  1 | PRIMARY     | Respuesta | REF  | id_usuario    | id_usuario | 2       | const |    2 | USING WHERE |
  7. |  2 | SUBQUERY    | Usuarios  | REF  | indice        | indice     | 11      |       |    1 | USING WHERE |
  8. +----+-------------+-----------+------+---------------+------------+---------+-------+------+-------------+
  9. 2 ROWS IN SET (0.01 sec)
  10.  
  11.  

Lo anterior repito es un mero ejemplo que sirve de guia basica para llevarte a tu objetivo.


Título: Re: Se puede hacer esto?
Publicado por: mark182 en 24 Noviembre 2009, 01:36 am
Muchísimas gracias nuevamente ^TiFa^ otra ves salvándome las papas jeje, justo estaba escribiendo mis tablas y demas a ver si me podrian dar un ejemplo porque la verdad que quede mariado. El sistema me informo que " mientras estabas escribiendo, una nueva respuesta fue publicada" y era justo lo que estaba pidiendo. Muchas gracias a vos y a todos los que han colaborado.

Aguante el foro de elhacker.net ! ! !    ;D


Título: Re: Se puede hacer esto?
Publicado por: ^Tifa^ en 24 Noviembre 2009, 19:22 pm
De nada encanto  :D   :D

Si tienes alguna duda mas cuando organizes tus ideas de las tablas, no dudes en preguntar nuevamente  ;)