0

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

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

条件:

  1. 如果帖子与圈子共享并且新用户添加到圈子中,那么他应该能够看到以前与该圈子共享的所有帖子。
  2. 如果用户从圈子中移除。(s) 他看不到与该圈子共享的帖子,除了他评论过的帖子。

目前我的数据库表是这样的。

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. 他们可以看到与他们共享的帖子(个人用户)。

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

问题:
首先,我已经能够从案例 1(查看所有公开帖子)、案例 2(与所有圈子共享的帖子)中获得帖子,但其他 2 个案例不起作用。我考虑了一下,发现主要问题是我指定了 where 子句来获取 p.is_public = 1 的帖子,这意味着它忽略了 p.is_public = 0 的行。我如何更新查询以显示涵盖所有内容的帖子四个案例,也涵盖了我们一开始谈到的条件。

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

4

1 回答 1

2

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

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

using join 意味着:保留 from 子句中使用的表中对于该 join 子句中指定的条件验证为 true 的所有行。

由于您使用的是 2 个语句,因此第一个连接会丢弃所有不需要连接的记录,第二个连接会丢弃第二个连接中没有所需连接的所有记录,但它只使用与第一个匹配的记录加入。

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

简单的例子:

用户表:

user_id
name

用户帖子

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)

这将使用所有用户并与该用户在一天前创建的每个帖子进行匹配,如果用户在最后一天没有发布,他仍将在结果集中,但帖子中的所有列表将为 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 子句每个加入声明(部分在评论中)

于 2013-02-03T13:00:18.923 回答