代码之家  ›  专栏  ›  技术社区  ›  Alec

MySQL数据库设计问题

  •  3
  • Alec  · 技术社区  · 15 年前

    情况
    假设我有以下内容:

    • 桌子 items
    • 桌子 lists 这些项目可以链接到
    • 桌子 users

    条件:列表可以属于 全部的 一特定 用户

    我想做的是创建一个“全局”列表,供永远的用户使用。但是应该有一种可能,用一个特定于用户的全局列表“覆盖”这个全局列表。随机用户示例:

    • 调用的全局列表
    • 用户特定列表 硫化镉

    现在,当检索此用户的列表时,我应该同时获得全局图书列表和用户特定的CD列表。但是如果这个用户有一个特定的图书列表呢?

    • 调用的全局列表
    • 用户特定列表
    • 用户特定列表 硫化镉

    所以现在它应该检索 用户专用性 列出被称为书籍而不是全局列表,当然还有用户特定的CD列表。

    可能的解决方案
    最简单的事情就是这样:

    table: lists
    - id
    - name
    - userId

    如果用户ID IS NULL 这意味着它是一个全球性的列表,但当它 NOT NULL 它属于特定用户。所以第一个例子是userid=1:

    id  name    userId
    1   books   NULL
    2   cds     1

    要检索此用户的列表:

    SELECT * FROM lists WHERE userId = 1 OR userId IS NULL

    但接下来我会陷入困境:

    id  name    userId
    1   books   NULL
    2   cds     1
    3   books   1

    这里的第一个列表“books”是一个全局列表,但是这个用户也有一个特定于用户的列表“books”。在这种情况下,可以忽略全局列表,只返回特定于用户的列表?

    另一种可能是创建一个 lists_users 表,将所有用户链接到所有全局列表,并在创建与其中一个全局列表同名的用户特定列表时删除此链接。不过,这似乎不是很有效,而且在添加新用户时需要维护更多的工作。

    问题 :
    在数据库中设置这个列表的最佳和最有效的方法是什么,以便我可以轻松地为特定用户检索正确的列表?

    3 回复  |  直到 15 年前
        1
  •  0
  •   Michael Pakhantsov    15 年前

    对于当前的设计,可以通过以下方式获取用户列表:

    SELECT * FROM lists 
    WHERE userId = 1 
    UNION ALL
    Select * from lists g 
    Where userId IS NULL
    AND NOT EXISTS (SELECT 1 from lists l where g.name = l.name and userid = 1)
    

    即选择特定于用户的列表和不由用户重新定义的全局

        2
  •  0
  •   Damir Sudarevic    15 年前

    如果你要过滤项目而不是列表呢?

    select distinct--来自用户特定列表的项
    项目名称
    ItemType
    从用户作为U
    在x.userid=u.userid上以x的形式加入userlist
    在t.listid=x.listid上以t形式加入列表
    在y.listid=t.listid上将listem作为y联接
    以m.itemID=t.itemID上的m形式联接项
    其中listType='自定义'
    and U.user id=一些用户
    联合
    选择不同
    itemname--全局列表中的项
    ItemType
    从t.listid=x.listid上的t列表
    在y.listid=t.listid上将listem作为y联接
    以m.itemID=t.itemID上的m形式联接项
    其中listType='global'
    
    按项目类型、项目名称排序
    ;
    < /代码> 
    
    

    Select distinct   -- items from user-specific lists 
          ItemName
        , ItemType
    from User     as u
    join UserList as x on x.UserId = u.UserId
    join List     as t on t.ListId = x.ListId
    join ListItem as y on y.ListId = t.ListId
    join Item     as m on m.ItemId = t.ItemId
    where ListType = 'custom'
    and u.UserId   = some_user_id
    UNION
    Select distinct 
          ItemName  -- items from global lists
        , ItemType
    from List     as t on t.ListId = x.ListId
    join ListItem as y on y.ListId = t.ListId
    join Item     as m on m.ItemId = t.ItemId
    where ListType = 'global'
    
    order by ItemType, ItemName
    ;
    

    alt text

        3
  •  0
  •   pleasedontbelong    15 年前

    我个人认为,当你开始在数据库中使用空值来解决一个概念问题时,这是因为你需要改变你的表。

    我建议这样做:(对于混乱的UML图感到抱歉)

    其背后的想法是,您可以使用“heritage”来分隔两种类型的列表:userdefinedList和defaultList。如您所见,只有用户定义列表与用户相关,并且默认列表对任何想要使用它们的用户都是开放的。当然,当有人想要创建列表时,您可以告诉用户列表已经创建,但实际上您不会在数据库中插入任何内容。

    当要显示用户列表时,将显示用户定义列表和所有默认列表。

    好吧,这听起来可能让人困惑,但这个故事的寓意是,当您拥有不同类型的元素(如列表)并且每种类型与其他表具有不同的关系(即,用户定义的列表与用户相关,而默认列表与用户无关,但它们都是列表类型)时,传统在数据库中是有用的。

    希望这有帮助

    l数据库中的值来解决概念问题,这是因为您需要更改表。

    我建议这样做:(对于混乱的UML图感到抱歉)

    List diagram

    其背后的想法是,您可以使用“heritage”来分隔两种类型的列表:userdefinedList和defaultList。如您所见,只有用户定义列表与用户相关,并且默认列表对任何想要使用它们的用户都是开放的。当然,当有人想要创建一个列表时 您可以告诉用户列表已经创建,但实际上您没有在数据库中插入任何内容。

    当要显示用户列表时,将显示用户定义列表和所有默认列表。

    好吧,这听起来可能让人困惑,但这个故事的寓意是,当您拥有不同类型的元素(如列表)并且每种类型与其他表具有不同的关系(即,用户定义的列表与用户相关,而默认列表与用户无关,但它们都是列表的类型)时,传统在数据库中是有用的。

    希望这有帮助