场合
说我有以下内容:
items
lists
users
条件:列表可以属于所有或一个特定的用户
我想做的是创建为所有用户而存在的“全局”列表。但应该有可能用一个特定于用户的列表“覆盖”这个全局列表。随机用户的示例:
现在,当检索此用户的列表时,我应该获得全局书籍列表和用户特定的cds列表。但是如果这个用户有一个特定的书籍列表呢?
所以现在它应该检索名为books的用户特定的列表而不是全局列表,当然还有用户特定的cds列表。
可能的解决方案
最简单的事情就是这样:
table: lists - id - name - userId
如果userId 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
表,将所有用户链接到所有全局列表,并在创建与这些全局列表之一具有相同名称的用户特定列表时删除此链接。这似乎并不是非常有效,并且在添加新用户时需要做更多的工作。
问题:
在数据库中设置它的最佳和最有效的方法是什么,以便我可以轻松地为特定用户检索正确的列表?
答案 0 :(得分:0)
对于您当前的设计,您可以通过以下方式获取用户列表:
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)
即。选择用户特定的列表和用户未重新定义的全局
答案 1 :(得分:0)
如果您要过滤项目而不是列表,该怎么办?
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
;
答案 2 :(得分:0)
在我个人看来,当你开始在数据库中使用NULL值来解决一个概念问题时,这是因为你需要改变你的表..
我建议:(抱歉凌乱的UML图表)
这背后的想法是你可以使用“遗产”来分离两种类型的列表:UserDefinedList和DefaultLists。如您所见,只有UserDefinedLists与Users相关,DefaultLists对任何想要使用它们的用户开放。当然,当有人想要创建列表书籍时,您可以告诉用户该列表已经创建,但实际上您没有在数据库中插入任何内容。
如果要显示用户列表,请显示UserDefinedLists和所有DefaultLists。
这可能听起来令人困惑,但故事的寓意是,当你有不同类型的元素(如列表)时,遗产在数据库中很有用,并且每种类型与其他表有不同的关系(即UserDefinedLists与用户和DefaultLists不是,但它们都是List的类型
希望这有帮助