2013-03-05 49 views
1

我目前有一个用户表,tblUser和一个用户类型表tblUserTypes数据库结构,用户和用户类型,其中用户可以是多个类型

这两者通过tblUser... fkUserTypeID中的外键链接进行链接。

因此目前用户只能是一种类型。

但是,有些情况下,用户可以是多种类型......比如说,一个Customer以及一个Supplier

给我最明显的解决方案是创建tblUsertblUserTypestblUser_UserTypes这是一个桥接表之间的新表:

[tblUser] ---<[tblUser_UserTypes]>--- [tblUserTypes] 

,但我可以看到的复杂性由此引发......例如,当导出加入到他们的用户类型的用户列表,用一个简单的连接,我将以多行这些用户结束。也许可以使用PIVOT查询将每条用户记录带回单行? (更多关于此)

将用户导入到系统中似乎也有问题...我目前使用文件中的BCP(批量复制过程)将用户直接导入到用户表中...导入文件包含在现有模型中工作的单个字段“用户类型”,因为每个用户当前只能是一种类型。但是,对于多种用户类型,我无法看到直接进入用户表的直接BCP是如何工作的。

增加了复杂性,用户类型目前不固定...表tblUserTypes是动态的...系统的一部分是允许创建任意数量的用户类型。但是,我需要知道某些类型的用户能够在更高级别定义业务逻辑.... “只允许在该区域使用type = x的用户”......所以有人建议,在用户类型表中有一系列标志定义了用户类型的类型(例如IsCustomer,IsSupplier

这感觉就像一个过于复杂的混乱,我正在睡觉如何前进。

我很想带给用户类型回表tblUser与完全其他两个表......一系列在user表中的复选框(如IsCustomerIsSupplier)......因为这使得进口的废除并直接出口。但那么用户类型不会是动态的。有趣的是,虽然用户类型不完全是动态的...因为如上所述,当谈到企业登录时,我需要了解一些用户类型。

嗯,它应该是两者的混合?我是否试图将两个特征压缩成一个?也许我可以在用户表中使用与业务逻辑相关的类型的复选框/布尔类型(例如IsCustomer,IsSupplier),并将"User Types"的上下文重命名为"User Groups"或类似的东西。

当考虑直接连接将导致用户被复制的结构时,我主要关心的是对导入,导出和搜索结果的影响......它们所属的每种用户类型都有一行。我将不得不做一个PIVOT查询来将这个返回给每个用户一个记录,每个用户类型都有一个列,对吗?一个实际的例子是一个拥有300万条记录并一次导入10000条记录的用户表......或者一次输出10000条记录......或者搜索这300万条记录以检索3,000条匹配,并以页面呈现在页面上以分页方式呈现,在那里他们可以在搜索结果页面中轻弹(我在搜索查询中使用ROWNUM与分页工作,我不返回每次都是)。

这是我在Stack Overflow上的第一个问题,对不起,如果它有点复杂或已经有答案列出...我试图搜索,但不能拿出处理与用户合作的复杂性的例子可以是多种类型。

哦,万一它很重要...这是一个C#ASP.NET应用程序与SQL Server一起工作。


通过它的思维和阅读的回答,我要去一路使用桥接表后...要求说,用户可以为多种类型的所以这是它怎么会。对现有代码的后果是戏剧性的,但现在比在赛道上更好。

我玩过表结构,并且需要在平面结构中获取数据所需的查询有点烦琐,最终需要动态SQL(因为用户类型列表是动态的),我不是粉丝但我看不到另一种方式来做到这一点。

在下面公司获取的例子是由一个“事件ID”,即过滤fkEventID

如果有更好的方法做了“扁平化”,我会:-)

非常感激的任何帮助


直截了当加入(每家公司多行,如果他们不止一种类型的)

select * from tblCompany 
left join tblCompany_CompanyType on fkCompanyID = pkCompanyID 
left join tblCompanyType on fkCompanyTypeID = pkCompanyTypeID 
where tblCompany.fkEventID = 1 


硬编码枢轴查询(每公司单排如果它们多于一种类型的,但该公司类型不是动态的)

select * from (
select tblCompany.*,tblCompanyType.CompanyType from tblCompany left join 
tblCompany_CompanyType on fkCompanyID = pkCompanyID 
left join tblCompanyType on fkCompanyTypeID = pkCompanyTypeID 
where tblCompany.fkEventID = 1 
) AS sourcequery 
Pivot (count(CompanyType) for CompanyType IN ([Customer],[Supplier],[Something Else])) as CompanyTypeName 


动态枢轴查询每(多行公司和处理动态公司类型)

DECLARE @cols AS NVARCHAR(MAX) 
DECLARE @sql AS NVARCHAR(MAX) 

SET @cols = STUFF(
(SELECT N',' + QUOTENAME(CompanyType) AS [text()] 
FROM (
select CompanyType from tblCompanyType 
where fkEventID = 1 
) AS Y 
FOR XML PATH('')), 
1, 1, N''); 

SET @sql = N'SELECT * FROM (
select tblCompany.*,tblCompanyType.CompanyType from tblCompany left join tblCompany_CompanyType on fkCompanyID = pkCompanyID 
left join tblCompanyType on fkCompanyTypeID = pkCompanyTypeID 
where tblCompany.fkEventID = 1 
) AS sourcequery 
Pivot (count(CompanyType) for CompanyType IN (' + @cols + ')) as CompanyTypeName 
order by pkCompanyID' 

EXEC sp_executesql @sql; 
+4

对于其中一个,请停止在桌子上放置愚蠢的'tbl'前缀。还有什么看法?所以呢?你仍然会像桌子一样对待它。把它称为'dbo.Users'。 – 2013-03-05 22:56:37

+2

此外,当您批量导入新用户时,您如何唯一标识用户为* new *?如果您导入一位名叫John Smith的新客户,那么John Smith与现有供应商John Smith相同吗? – 2013-03-05 22:59:51

+1

最后,同一个用户回来多次的问题是什么?您始终可以按用户类型进行过滤,也可以让应用程序/表示层为同一用户折叠多行。 – 2013-03-05 23:00:56

回答

0

你真正做到有许多用户和用户类型之间一对多的关系,我建议你继续前进,实现我那样。

如果您在某些情况下需要查看它变平,可以使用视图或存储过程来调整它。

如果要继续使用BCP导入,可以将BCP始终装入临时表中,然后使用存储的过程来填写您的3个表。无论如何,这样做可能更安全。

坚持全面实施多对多关系将为您提供应用程序最大的灵活性,并防止您在获得新安全角色的新需求时不需要不断修改用户表。

+0

你说得对。我正在懒惰,试图避免一路走来......我已经有很多已经开发出来的代码,这个核心实体结构的变化将大大摇摆船!......但我要去必须把这一个粉笔记录下来,然后把它放在下巴上。 我会照你所建议的那样做:将文件BCP到暂存表中,并从那里使用它。 我会计划使用PIVOT查询结构发布答案,以便将数据平整在需要的地方...可能会帮助其他人。 – 2013-03-06 01:48:57