Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Join different tables depending on field values

I have the following sql view result which contains the audited changes for every field for every table in the system:

enter image description here

In this case the above image tell us that both read and write permissions were revoked for the user Lucas for the subscription called MySubscription.

I need to display that info in a grid however that is not what I want to display, I mean, I don´t want to display IDs. I need to display "Read" instead of 50, "Write" instead of 51, "Lucas" instead of 1 and "MySubscription" instead of 6.

To do that I would like to improve the sql view to get the values instead of their IDs as I mention above. The result that I am looking for is this one: enter image description here

The database contains the tables Subscriptions, ProductPermissions and TenantUsers to get the needed info using joins.

Could you please give me some clues about how could I achieve what I need? Thank you.

like image 492
lontivero Avatar asked Aug 20 '26 09:08

lontivero


1 Answers

You could do this with a series of LEFT JOINs, some casting might be required to get the datatype of the joining column the same as NewValue (I've assumed a column called Name in all your joining tables, this may need changing):

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'

If required you could then PIVOT this into one row per transaction:

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;

It is a pretty dirty solution, I would be inclined to store this data in the format you want to select it in i.e. instead of 50/51, store read/write directly in the NewValue column.

Alternatively, if you did want the second format with one row per transaction then I'd be inclined to store it in this way. It could be worth reading about the Entity-Attribute-Value Antipattern.

like image 56
GarethD Avatar answered Aug 22 '26 00:08

GarethD



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!