Pregunta
Así que estoy tratando de construir un foro simple. Será una lista de temas en orden descendente según la fecha del tema (si no hay respuestas) o la respuesta más reciente. Aquí está la estructura de DB:
forum_topic
ID, nombre, correo electrónico, cuerpo, fecha
forum_reply
ID, correo electrónico, cuerpo, fecha, ID de tema
El foro en sí constará de una tabla HTML con los siguientes encabezados:
Tema, última modificación, # respuestas
¿Cómo se vería la consulta o las consultas para producir tal estructura? Estaba pensando que implicaría una unión cruzada, pero no estoy seguro ... Gracias de antemano.
Solución
En primer lugar, me parece que noboody en realidad está respondiendo a tu pregunta, que fue:
¿Cómo se vería la consulta o las consultas para producir dicha estructura?
con una estructura solicitada de
Tema, última modificación, # respuestas.
El SQL para producir una tabla de resultados con esa estructura, dadas las estructuras de tablas que proporcionó, sería:
SELECT t.Id, t.Name AS Topic,
MAX(r.Date) AS LastModified,
COUNT(*) AS NumReplies
FROM Forum_Topic t
LEFT OUTER JOIN Forum_Reply r ON t.id = r.topic_id
GROUP BY t.Id, t.Name
(lo siento, esto se prueba solo en SQL Server, ya que no tengo acceso a MySql en este momento)
Además, su estructura ES ya está normalizada. Las sugerencias de lo contrario hacen suposiciones sobre lo que desea hacer, por ejemplo, suponiendo que está interesado en rastrear los nombres de usuario en adición a las direcciones de correo electrónico. Esto es bastante razonable, pero sin embargo es un supuesto. No hay nada de malo, desde una perspectiva de normalización, con el uso de la dirección de correo electrónico como un identificador de usuario único.
Ahora, si está buscando sugerencias generales sobre cómo configurar una base de datos, podemos darle MUCHAS de ellas. Antes de la normalización, comenzaría por no usar palabras clave potenciales como nombres de objetos (por ejemplo, no dar nombres de columnas como 'Nombre' y 'Fecha').
En cuanto al comentario de Matt sobre el valor que es NULL cuando no hay respuestas: el uso de la función COALESCE () lo solucionará. COALESCE () devuelve el primer argumento no NULL (o NULL si todos los argumentos son NULL). Entonces reemplace el MAX (r.Date) con MAX (COALESCE (r.Date, t.Date)).
Otros consejos
Algo así:
select * from forum_topic
inner join forum_reply on forum_topic.id=topc_id
Sin embargo, no uses select *
Eso es una mala práctica :)
¡Y no me gusta la forma en que evitas la normalización! Lo que significa que preferiría tener:
Usuarios
- ID de usuario
- nombre
- correo electrónico
Hilos
- ThreadID
- Asunto
- Respondido
- AskedByUserID
- fecha
Respuestas
- ReplyID
- ThreadID
- ID de usuario
- Respuesta
- fecha
Luego seleccionando un tema como este:
select ThreadID, Subject, Answered, AksedByUserID, Date from Threads
Y seleccionando todas las respuestas como esta
select Answer, Date, Name, Email from Threads
inner join Replies on Threads,ThreaID=Replies.ThreadID
inner join Users on AskedByUserID=UserID
where Threads.ThreadID=xxx
Esto se acaba de escribir desde la parte superior de mi cabeza, pero también es posible que tengas que agregar algún grupo.
Sí, debería poder obtenerlo con una consulta como esta:
SELECT
forum_topic.id,
forum_topic.name AS Topic,
MAX(forum_reply.date) AS Last_Modified,
count(*) AS Replies
FROM forum_topic
INNER JOIN forum_reply ON (forum_topic.id=forum_reply.topic_id)
GROUP BY forum_topic.id
El grupo " por " es la magia que nos da una fila por tema, con MAX () y Las funciones COUNT () nos proporcionan los datos agregados que necesita.
(EDIT: me perdí que el cuerpo de la primera publicación estuviera en la tabla de temas, por lo que las consultas sin respuestas se perderían con la consulta anterior. Filip tiene la idea correcta que sugiere que normalice sus datos. Una vez que se haya normalizado , una consulta similar a la anterior le proporcionará los datos que necesita).
Por " normalizado ", quiere decir que la columna del cuerpo de " forum_topic " debe eliminarse, y el cuerpo del tema real debe ser la primera respuesta?