1

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

在此处输入图像描述

在这种情况下,上图告诉我们,用户Lucas对名为MySubscription的订阅的读取写入权限都被撤销了。

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

为此,我想改进 sql 视图以获取值而不是我上面提到的它们的 ID。我正在寻找的结果是这个: 在此处输入图像描述

该数据库包含表SubscriptionsProductPermissionsTenantUsers以使用联接获取所需的信息。

您能否给我一些关于如何实现我需要的线索?谢谢你。

4

4 回答 4

2

您可以使用一系列LEFT JOINs 来执行此操作,可能需要进行一些转换才能使连接列的数据类型与NewValue(我假设Name在所有连接表中都调用了一个列,这可能需要更改):

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'

如果需要,您可以在每个事务中将其 PIVOT 为一行:

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;

这是一个非常肮脏的解决方案,我倾向于以您想要选择的格式存储这些数据,而不是 50/51,直接在NewValue列中存储读/写。

或者,如果您确实想要每笔交易一行的第二种格式,那么我倾向于以这种方式存储它。关于Entity-Attribute-Value Antipattern可能值得一读。

于 2013-01-21T14:55:12.107 回答
0

您可以PIVOT将数据和LEFT JOIN查找表。然后UNPIVOT如果有必要。

于 2013-01-21T14:34:08.883 回答
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;
于 2013-01-21T14:34:09.997 回答
0

您可以尝试加入您的表,其中您的值是特定的。您需要为其他值创建一个查找表,而不是真的这是一个肮脏的解决方案,因为这意味着将您的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
...

这可能对你有用。

于 2013-01-21T14:38:29.160 回答