dongwen1935 2013-02-03 12:25
浏览 18
已采纳

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

I'm building a site that requires sharing with either group(s) or individual user(s). I know for a fact that google does not use mysql, but i was wondering how i could replicate such feature on my site. On g+, one can:

  1. Share a post with the "public" (everyone can see it).
  2. Share a post with "all circles" (everyone in your circles can see it).
  3. Share a post with both circles and individual users. E.g. post = "my first post" and is shared with family,friends, user 1(Joey tribbiani), user 2 (Ross geller) etc.

Conditions:

  1. If a post is shared with a circle and a new user is added to the circle, then (s)he should be able to see all the previous posts shared with that circle.
  2. If a user is removed from a circle. (s)he cannot see posts shared with that circle except posts (s)he has commented on.

Currently my database tables look like this.

Circle_category

Cat_id
Cat_name
user_id

Posts

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

Post a user in family circle(which is in Circle_category with cat_id of 1 ) can see

  1. They can see posts that are public.
  2. They can see posts shared with all circles.
  3. They can see posts shared with family circle.
  4. They can see posts shared with them (Individual user).

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:
Firstly, I've been able to get posts from case 1(see all public post), case 2 (Posts shared with all circles) but the other 2 cases do not work. I thought about it and saw that the main problem is that i specified the where clause to get posts where p.is_public = 1 which means it neglets rows where p.is_public = 0. How do i update the query so it shows posts covering all four cases and also covers the conditions we talked about at the beginning.

Secondly, is there a better way to structure my tables? i'm not sure i'm doing it the right way.

  • 写回答

1条回答 默认 最新

  • douqiang3768 2013-02-03 13:00
    关注

    From a quick read trough, all i can say is:

    you are using a join statement instead of a left join statement.

    using join means: keep all rows from the table used in from-clause that validate true for the condition specified in that join clause.

    since you are using 2 statements, the first join throws away all the records that dont have the needed join, the second join throws away all the records that dont have the needed join in the second one, but it only uses records that matched the first join.

    you should use left join instead. this keeps all rows from the first table. all rows that didnt have a match, get the values NULL for the columns specified in the joined table(s)

    simple example:

    users table:

    user_id
    name
    

    user_posts

    post_id
    user_id
    content
    created
    

    related queries:

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

    this will use all users and make match with each post that was created less then a day ago by that user. if the user didnt have a post in the last day, he will NOT be in the resultset.

    change this example to

    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)
    

    this will use all users and make a match with each post that was created less then a day ago by that user if the user hasn't posted in the last day, he will STILL be in the resultset, but all the columns from the posts table will be NULL

    the where filters all the rows you have left after the joins. (mysql will use where clauses before joining, if they can speed up the query).

    altering your query:

    make sure the clauses in where statement are wrapped between () for all the different cases. ALSO this is NOT the complete answer, as there is info missing (example user tables, circle relation tables, friend relations)

    also the all_circles option confuses me, so it's missing from the query, but this should get you on the right track

    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
    )
    

    Also, i'm suspecting you'll need 2 subqueries, which is not the best thing to do, and my advise would be to find all correct ids for the friends, and all ids for the valid circles and then using an IN clause in each join statement (part thats in comment)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c