我应该重新设计我的桌子还是可以让它工作?

时间:2013-08-02 00:32:35

标签: mysql

现在我正在努力将我的网站扩展到新功能。我想启用来自不同来源的通知。类似于facebook上的群组和人物。这是我现在的表格布局。

course_updates
id | CRN (id of course) | update_id
------------------------------------
courses
id | course_name | course_subject | course_number
-------------------------------------------------
users
id | name | facebook_name
---------------------------------------------------

user_updates
id | user_id | update_id
------------------------

updates
id | timestamp | updateObj
---------------------------

我希望能够做的是在一个查询中使用course_update和user_updates,并将它们与更新以及表的正确信息一起加入。所以对于course_updates我想要course_name,course_subject等,而对于user_updates,我想要用户名和facebook名称。这老实说可能属于两个单独的查询,但我想按更新表的时间戳排列所有内容,我觉得在php中排序一切都效率低下。做这个的最好方式是什么?我需要一种方法来区分通知类型,如果我使用像union这样的东西,因为user_updates和course_updates可以存储对更新中同一列的引用。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

您可能根本不需要updates表。您可以将时间戳列添加到course_updatesuser_updates

CREATE TABLE course_updates
(
  `id` int, 
  `CRN` int, 
  `timestamp` datetime -- or timestamp type
);
CREATE TABLE user_updates
(
  `id` int, 
  `user_id` int, 
  `timestamp` datetime -- or timestamp type
);

现在要获得所有更新的有序和列级统一结果集,您可能会发现在一列中使用分隔字符串(使用CONCAT_WS())打包每种更新类型的更新详细信息很方便(让我们称之为{ {1}}),注入一列来区分更新类型(让我们称之为details)并使用obj_type

UNION ALL

示例输出:

| OBJ_TYPE | ID |                   TIMESTAMP |                 DETAILS |
-------------------------------------------------------------------------
|        C |  3 | July, 30 2013 22:00:00+0000 | 3|Course3|Subject3|1414 |
|        U |  2 | July, 11 2013 14:00:00+0000 |        1|Name1|FB Name1 |
|        U |  2 | July, 11 2013 14:00:00+0000 |        3|Name3|FB Name3 |
...

这是 SQLFiddle 演示

然后,当您在php中迭代结果集时,可以轻松地SELECT 'C' obj_type, u.id, u.timestamp, CONCAT_WS('|', c.id, c.course_name, c.course_subject, c.course_number) details FROM course_updates u JOIN courses c ON u.CRN = c.id UNION ALL SELECT 'U' obj_type, u.id, u.timestamp, CONCAT_WS('|', s.id, s.name, s.facebook_name) details FROM user_updates u JOIN users s ON u.user_id = u.id ORDER BY timestamp DESC 详细说明值。

答案 1 :(得分:0)

我认为您不应该在查询中将这两个概念(用户和课程)混合在一起。它们具有不同数量的列并且与不同的概念相关。

我认为你真的应该使用两个查询。一个用户,一个用于课程。

SELECT courses.course_name, courses.course_subject, courses.course_number,   
       updates.updateObj,updates.timestamp
FROM courses, updates, course_updates
WHERE courses.id = course_updates.course_id
    AND course_updates.udpate_id = updates.id
ORDER BY updates.timestamp;

SELECT users.name,users.facebook_name,updates.updateObj,updates.timestamp
FROM users ,updates, user_updates
WHERE users.id = user_updates.user_id
    AND  user_updates.update_id = updates.id
ORDER BY updates.timestamp;

答案 2 :(得分:0)

如果你要合并两个表,你需要记住两件事:

  1. 理想情况下列数应相同
  2. 应该有办法区分数据来源。
  3. 以下是一种可以做到这一点的方法:

    SELECT * FROM
       (SELECT courses.course_name as name, courses.course_subject as details,
               updates.updateObj as updateObj, updates.timestamp as timestamp,
               "course" as type
        FROM courses, updates, course_updates
        WHERE courses.id = course_updates.course_id
        AND course_updates.udpate_id = updates.id)
       UNION ALL
        SELECT users.name as name,users.facebook_name as details,
               updates.updateObj as updateObj,updates.timestamp as timestamp,
               "user" as type
        FROM users ,updates, user_updates
        WHERE users.id = user_updates.user_id
        AND  user_updates.update_id = updates.id) as out_table
    ORDER BY out_table.timestamp DESC
    

    type可让您区分用户和课程更新,前端可以使用它来为行添加不同的颜色。 course_id没有出现在此,但您可以添加它,请记住,您必须向用户select语句添加一些虚拟文本,以确保两个查询返回相同的行数。请注意,如果有涉及用户和课程的更新,它将出现两次。

    您也可以按type订购,以区分用户和课程数据。