用户指定的内容共享,如G +

时间:2013-02-03 12:25:25

标签: php mysql sql database database-design

我正在构建一个需要与群组或个人用户共享的网站。我知道google不使用mysql的事实,但我想知道如何在我的网站上复制这样的功能。在g +上,可以:

  1. 与“公众”分享帖子(每个人都可以看到)。
  2. 与“所有圈子”分享信息(圈子中的每个人都可以看到它)。
  3. 与圈子和个人用户分享信息。例如。 post =“我的第一篇文章”并与家人,朋友,用户1(Joey tribbiani),用户2(Ross geller)等分享。
  4. 条件:

    1. 如果帖子与圈子共享并且新用户被添加到圈子中,那么他应该能够看到与该圈子共享的所有先前帖子。
    2. 如果用户已从圈子中删除。 (s)除了他评论过的帖子外,他看不到与该圈子分享的帖子。
    3. 目前我的数据库表格如下所示。

      Circle_category

      Cat_id
      Cat_name
      user_id
      

      帖子

      post_id 
      user_id
      post
      is_public
      all_circle
      

      Post_to_circle

      entry_id
      post_id
      cat_id
      

      Post_to_user

      entry_id
      post_id
      user_id
      

      在家庭圈子中发布用户(在Circle_category中,cat_id为1)可以看到

      1. 他们可以看到公开的帖子。
      2. 他们可以看到与所有圈子分享的帖子。
      3. 他们可以看到与家人圈子分享的帖子。
      4. 他们可以看到与他们分享的帖子(个人用户)。
      5. SQL

         SELECT p.* FROM posts p
            JOIN Post_to_circle pc
            ON p.post_id = pc.post_id
            JOIN Post_to_user pu
            ON p.post_id = pu.post_id
            WHERE p.is_public = 1 
            OR all_circle = 1
            OR pc.cat_id = $cat_id 
            OR pu.user_id = $user_id
        

        Quetions:
        首先,我已经能够从案例1(见所有公开帖子),案例2(与所有圈子分享的帖子)中获得帖子,但其他2个案例不起作用。我想到了它,并看到主要的问题是我指定了where子句来获取p.is_public = 1的帖子,这意味着它在p.is_public = 0的地方行。如何更新查询以便显示覆盖所有的帖子四个案例,也涵盖了我们在开始时谈到的条件。

        其次,有没有更好的方法来构建我的表格?我不确定我是以正确的方式做到的。

1 个答案:

答案 0 :(得分:2)

从快速阅读的低谷,我只能说:

您正在使用连接语句而不是左连接语句。

使用连接方式: 保留from子句中使用的表中的所有行,该表对于该join子句中指定的条件验证为true。

因为你使用了2个语句,所以第一个连接抛弃了没有所需连接的所有记录,第二个连接抛弃了在第二个连接中没有所需连接的所有记录,但它只使用了匹配第一次加入。

你应该使用左连接。这将保留第一个表中的所有行。所有没有匹配的行,为连接表中指定的列获取值NULL

简单的例子:

用户表:

user_id
name

user_posts

post_id
user_id
content
created

相关查询:

select *
from users u
JOIN user_posts up on up.user_id = u.user_id and up.created > date_sub(curdate(), interval 1 day)

这将使用所有用户并与该用户在一天前创建的每个帖子匹配。 如果用户在最后一天没有帖子,他将不在结果集中。

将此示例更改为

select *
from users u
LEFT JOIN user_posts up on up.user_id = u.user_id and up.created > date_sub(curdate(), interval 1 day)

这将使用所有用户并与该用户在一天前创建的每个帖子进行匹配 如果用户在最后一天没有发布,他仍然会在结果集中,但是posts表中的所有列都将为NULL

where会过滤连接后剩下的所有行。 (mysql将在加入前使用where子句,如果它们可以加速查询)。

更改您的查询:

确保where语句中的子句包含在()之间,用于所有不同的情况。这也不是完整的答案,因为缺少信息(示例用户表,圆关系表,朋友关系)

all_circles选项也让我感到困惑,因此查询中缺少它,但这可以让你走上正确的轨道

SELECT p.* FROM posts p
    left JOIN Post_to_circle pc
    ON p.post_id = pc.post_id and /* define statement for valid circles for user you're trying to get the posts for */
    left JOIN Post_to_user pu
    ON p.post_id = pu.post_id and /* define statement for valid friends for user you're trying to get the posts for */
    WHERE 
/* 1 day old */
p.created > date_sub(curdate(), interval 1 day)
AND (
/* is public */
p.is_public = 1 OR
/* or to friends */
pu.id is not null OR
/* or to circles */
pc.id is not null
)

另外,我怀疑你需要2个子查询,这不是最好的事情,我的建议是为朋友找到所有正确的ID,有效圈子的所有ID,然后使用每个连接语句中的IN子句(注释中的部分)