根据字段值加入不同的表

时间:2013-01-21 14:23:46

标签: sql sql-server sql-server-2008 tsql join

我有以下sql视图结果,其中包含系统中每个表的每个字段的审计更改:

enter image description here

在这种情况下,上面的图片告诉我们,对于名为 Lucas 已撤消读取写入权限> MySubscription 。

我需要在网格中显示该信息,但这不是我想要显示的内容,我的意思是,我不想显示ID。我需要显示“Read”而不是50,“Write”而不是51,“Lucas”而不是1和“MySubscription”而不是6。

要做到这一点,我想改进sql视图以获取值而不是他们的ID,如上所述。我正在寻找的结果是这一个: enter image description here

数据库包含表订阅 ProductPermissions TenantUsers 以使用连接获取所需信息。

请您告诉我一些关于如何实现我需要的线索?谢谢。

4 个答案:

答案 0 :(得分:2)

您可以使用一系列LEFT JOIN执行此操作,可能需要某些转换才能使加入列的数据类型与NewValue相同(我假设了一个名为{{1的列)在所有连接表中,这可能需要更改):

Name

如果需要,您可以将每个事务PIVOT分成一行:

SELECT  a.AuditLogId,
        a.Operation,
        a.[Table],
        a.RowId,
        a.Name,
        [OldValue] = COALESCE(s_Old.Name, pp_old.Name, t_Old.Name),
        [NewValue] = COALESCE(s_New.Name, pp_New.Name, t_New.Name)
FROM    AuditLog a
        LEFT JOIN Subscriptions s_Old
            ON a.OldValue = CAST(s_Old.SubscriptionID AS VARCHAR)
            AND a.Name = 'SubscriptionID'
        LEFT JOIN ProductPermissions pp_Old
            ON a.OldValue = CAST(p_Old.ProductPermissionID AS VARCHAR)
            AND a.Name = 'ProductPermissionId'
        LEFT JOIN TenantUsers t_Old
            ON a.OldValue = CAST(t_Old.TenantUserId AS VARCHAR)
            AND a.Name = 'TenantUsers'
        LEFT JOIN Subscriptions s_New
            ON a.NewValue = CAST(s_New.SubscriptionID AS VARCHAR)
            AND a.Name = 'SubscriptionID'
        LEFT JOIN ProductPermissions pp_New
            ON a.NewValue = CAST(p_New.ProductPermissionID AS VARCHAR)
            AND a.Name = 'ProductPermissionId'
        LEFT JOIN TenantUsers t_New
            ON a.NewValue = CAST(t_New.TenantUserId AS VARCHAR)
            AND a.Name = 'TenantUsers'

这是一个非常脏的解决方案,我倾向于以您想要选择它的格式存储这些数据,而不是50/51,直接在SELECT a.AuditLogId, a.Operation, a.[Table], a.RowId, [OldSubscriptionValue] = MAX(s_old.Name), [OldProductPermissionValue] = MAX(pp_old.Name), [OldTennantUserValue] = MAX(t_old.Name), [NewSubscriptionValue] = MAX(s_New.Name), [NewProductPermissionValue] = MAX(pp_New.Name), [NewTennantUserValue] = MAX(t_New.Name) FROM AuditLog a LEFT JOIN Subscriptions s_Old ON a.OldValue = CAST(s_Old.SubscriptionID AS VARCHAR) AND a.Name = 'SubscriptionID' LEFT JOIN ProductPermissions pp_Old ON a.OldValue = CAST(p_Old.ProductPermissionID AS VARCHAR) AND a.Name = 'ProductPermissionId' LEFT JOIN TenantUsers t_Old ON a.OldValue = CAST(t_Old.TenantUserId AS VARCHAR) AND a.Name = 'TenantUsers' LEFT JOIN Subscriptions s_New ON a.NewValue = CAST(s_New.SubscriptionID AS VARCHAR) AND a.Name = 'SubscriptionID' LEFT JOIN ProductPermissions pp_New ON a.NewValue = CAST(p_New.ProductPermissionID AS VARCHAR) AND a.Name = 'ProductPermissionId' LEFT JOIN TenantUsers t_New ON a.NewValue = CAST(t_New.TenantUserId AS VARCHAR) AND a.Name = 'TenantUsers' GROUP BY a.AuditLogId, a.Operation, a.[Table], a.RowId; 列存储读/写。

或者,如果您确实希望第二种格式每个事务有一行,那么我倾向于以这种方式存储它。值得一读的是Entity-Attribute-Value Antipattern

答案 1 :(得分:0)

您可以PIVOT数据和LEFT JOIN查找表。如有必要,请UNPIVOT

答案 2 :(得分:0)

如果您只需要显示单词而不是数字,请创建一个查找表,在您要显示的数字和单词之间进行映射:

create table NewValueText (
    NewValue integer,
    Description char(20)
);

insert into NewValueText values
   (50, 'Read'),
   (51, 'Write');   --etc.

--MyTable is your table that contains the NewValue column.
select Description from MyTable
    inner join NewValueText on MyTable.NewValue = NewValueText.NewValue;

答案 3 :(得分:0)

您可以尝试加入特定值的表格。您需要为除了Really之外的其他值创建一个查找表,这是一个肮脏的解决方案,因为这意味着将NewValue字段硬编码到SQL中:

...
FROM
    audit LEFT JOIN 
    mysubscription ON audit.rowid = mysubscription.tenantuserid
        AND audit.newvalue = 1
    LEFT JOIN 
    lookup_list ON audit.rowid = lookup_list.lookup_id 
        AND audit.newvalue <> 1
...

这可能适合你。