【问题标题】:Given 2 tables, how to consolidate them into a view?给定 2 个表,如何将它们合并到一个视图中?
【发布时间】:2020-07-10 03:51:03
【问题描述】:

鉴于以下 ADuser 表:

AD Group    UserID
Group1      User1
Group2      User2
Group3      User1
Group3      User3

Group_Access表:

AD Group    Org Codes
Group1   M500_ABC|1098|123_KL|Z45557|f908L_P|234G|
Group2   123_KL|Z45557|f908L_P|
Group3   12345|

我如何将它们合并到一个视图中,以便我们最终得到这样的结果,其中组织代码组合在 1 个匹配的用户 ID 下?

UserID      Org Codes
User1       M500_ABC|1098|123_KL|Z45557|f908L_P|234G|12345|
User2       123_KL|Z45557|f908L_P|
User3       12345|

请注意,由于 User1 属于多个组,即 Group1 和 Group3,因此 user1 的这 2 个组中的所有组织代码在最终视图中合并为 1,附加额外的 12345| 组织代码

到目前为止我尝试了什么:

CREATE VIEW UserOrgCodesView
AS SELECT ADuser.UserID, Group_Access.[Org Codes]
FROM ADuser
INNER JOIN Group_Access ON ADuser.[AD Group]=Group_Access.[AD Group];

但这已经在下面产生了

UserID  Org Codes
User1   M500_ABC|1098|123_KL|Z45557|f908L_P|234G|12345|
User2   123_KL|Z45557|f908L_P|
User1   12345|
User3   12345|

【问题讨论】:

  • @DaleK 我更新了帖子
  • 连接无效,因为AD Group 列具有不同的格式 - Group1AD_Group1 无法在未经操作的情况下连接。
  • @AlwaysLearning 哦,天哪,你说得对。我犯了一个严重的错误哈哈。现在我得到了一些回报,但是,我不知道如何将同一个用户合并到一个组织代码行中。请检查更新的帖子

标签: sql-server sql-server-2017


【解决方案1】:

组织代码在哪里组合在 1 个匹配的用户 ID 下?

You'll need to use STRING_AGG which is only available in SQL Server 2017 or later.

此查询还在输入[Org Codes] 值上使用TRIM(),以帮助防止'||' 在现有字符串连接在一起时出现在输出中。

SELECT
    u.UserId,
    STRING_AGG( TRIM( '|' FROM g.[Org Codes] ), '|' ) AS [Org Codes]
FROM
    ADuser AS u
    INNER JOIN Group_Access AS g ON u.[AD Group] = g.[AD Group]
GROUP BY
    u.UserId;

也就是说,像这样对数据进行非规范化通常是个坏主意。您应该将面向行的数据返回给客户端,并且只对 UI 层中的数据进行非规范化。

【讨论】:

  • 当我为视图添加 AS 时出现错误:CREATE VIEW [dbo].[UserOrgCodesView] AS SELECT u.Us....。它说 CREATE VIEW 必须是该批次中唯一的声明......我怀疑它是因为我有“Go”。我删除了它,但仍在抱怨
  • 关于非规范化数据,你说得对,我们确实讨论过它,但不幸的是,这是我们实现这一点的唯一方法。我们想到了许多解决方案,但它们都有局限性,这是执行和实施明智的唯一方法。例如,我们尝试使用具有多个 Access 列的表,但这限制了我们正在构建的安全性的层次结构。我们还尝试在 excel 中使用 DAX 公式,但它将组织代码的搜索限制为 1 个用户。
【解决方案2】:

您可以使用STRING_AGG(如果 SQL Server 2017 及更高版本)或XML PATH(如果 SQL Server 2017 之前)。

CREATE TABLE aduser (ADGroup SYSNAME, UserID sysName)

create table group_access (ADgroup sysname, OrgCodes VARCHAR(4000))

insert into aduser values
('Group1','User1'),
('Group2','User1');

insert into group_access values
('Group1','M500_ABC|1098|123_KL|Z45557|f908L_P|234G|'),
('Group2',' 123_KL|Z45557|f908L_P|')

CREATE VIEW UserOrgCodesView_SQL2017onwards
AS
SELECT ad.UserID, STRING_AGG(gc.OrgCodes,'') as Orgcodes 
FROM aduser as ad
inner join group_access as gc
on gc.ADGroup = ad.ADGroup
group by ad.UserID

CREATE VIEW UsersOrgCodesView_Before2017
as
SELECT oad.UserID, STUFF((SELECT gc.OrgCodes+'' FROM group_access as gc
inner join aduser as ad
on gc.ADGroup = ad.ADGroup 
where ad.UserID = oad.UserID
FOR XML PATH('')),1,0,'') as Orgcodes 
FROM aduser as oad
group by Oad.UserID

【讨论】:

  • 顺便说一句,如果我没有尾随分隔符怎么办,例如123_KL|Z45557|f908L_Pnotice no |在末尾。这会影响解决方案吗?
  • @Cataster,对于 SQL 2017 及更高版本没有问题。对于早期版本,我已经更新了我的答案
  • 这是否适用于两种情况,如果我有,如果我没有尾随 |分隔符?
  • 太棒了。如果你不介意,还有一个问题。如果我们有另一个要求来创建另一个视图,该视图具有相同的结果,但也包含 ADGroup,并且已合并?例如,User1 属于 Groups1 和 3 对吗?那么会有 3 列,ADGroup, UserID,Org Codes 值第一行:Group1|Group3 User1 M500_ABC|1098|123_KL|Z45557|f908L_P|234G|12345|
  • @Cataster,是的。您可以使用相同的逻辑来连接groups,因为我们已经连接了orgcodes
【解决方案3】:

您可以尝试以下方法:

CREATE TABLE TmpTblADUser (GroupName VARCHAR(10), UserID VARCHAR(10));
INSERT INTO TmpTblGroupAccess VALUES
  ('Group1', 'M500_ABC|1098|123_KL|Z45557|f908L_P|234G|'),
  ('Group2', '123_KL|Z45557|f908L_P|'),
  ('Group3', '12345|')



CREATE TABLE TmpTblGroupAccess (GroupName VARCHAR(10), OrgCodes VARCHAR(1000));
INSERT INTO TmpTblGroupAccess VALUES
('Group1', 'M500_ABC|1098|123_KL|Z45557|f908L_P|234G|'),
('Group2', '123_KL|Z45557|f908L_P|'),
('Group3', '12345|')

CREATE VIEW UserOrgCodesView
AS SELECT u.UserID, g.OrgCodes
FROM TmpTblADUser u
INNER JOIN TmpTblGroupAccess g ON u.GroupName = g.GroupName;


SELECT t.UserID,
       STUFF((SELECT OrgCodes + '' FROM UserOrgCodesView WHERE UserID = t.UserID FOR XML PATH ('')), 1, 0, '') AS GrupList  
       FROM UserOrgCodesView t
GROUP BY t.UserID

【讨论】:

  • 这也是一个不错的答案!我看到您只是加入视图,但合并是通过独立运行 SELECT 语句临时发生的。您如何将最后的 SELECT 语句与 CREATE VIEW 结合起来?您可以在不删除第一个解决方案的情况下发布第二个编辑吗?
  • 我在您的问题中使用了视图定义。我删除了不必要的 LEFT 函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 2020-04-17
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 2013-12-14
相关资源
最近更新 更多