0

SQLビュークエリに問題があります。いくつかの重複したクエリがありますが、そのままにしてはいけないと思います。これは、より大きなもののほんの一部です。

    WITH auditlogs ([AuditLogId], [OperationCode], [Operation], [Table], [RowId], [Timestamp], [UserUid], [UserName], [IpAddress], [OperationSet], [ContextUid], [Field], [OldValue], [NewValue]) AS
    (
        SELECT
            al.[Id] AS [AuditLogId],
            al.[Operation] as [OperationCode],
            CASE al.[Operation]
                WHEN 0 THEN 'New'  
                WHEN 1 THEN 'Update'  
                WHEN 2 THEN 'Delete'  
                ELSE 'Warning'  
            END  AS [Operation],
            al.[EntityName] AS [Table],
            CASE al.[EntityId] 
                WHEN -1 THEN NULL
                ELSE al.[EntityId] 
            END AS [RowId],
            al.[Timestamp],
            al.[UserUid],
            al.[UserName],
            al.[IpAddress],
            al.[OperationSet],
            al.[ContextUid],
            alf.[Name],
            alf.[OldValue],
            alf.[NewValue]
        FROM [AuditLog] AS al
            INNER JOIN [AuditLogField] AS alf ON alf.AuditLogId = al.Id
    )
    SELECT [AuditLogId], --- ATTACHUSERS
        [OperationCode], [Operation], [Table], [RowId], [Timestamp], alx.[UserUid], [UserName], 
        [IpAddress], [OperationSet], [ContextUid], 'User' AS [Field], null, u.[FirstName] + ' ' + u.[LastName], s.Id
    FROM (
        SELECT [AuditLogId],
            [OperationCode], [Operation], [Table], [RowId], [Timestamp], [UserUid], [UserName], 
            [IpAddress], [OperationSet], [ContextUid],
            MAX(case when [Field] = 'UserUid' then [NewValue] end) AS AddedUserUid,
            MAX(case when [Field] = 'TenantId' then [NewValue] end) TenantId
        FROM [auditlogs] AS al
        WHERE al.[Table] = 'TenantUser' AND OperationCode = 0
        GROUP BY [AuditLogId], [OperationCode], [Operation], [Table], [RowId], [Timestamp], al.[UserUid], [UserName], 
            [IpAddress], [OperationSet], [ContextUid]
    ) AS alx
    INNER JOIN [User] AS u ON u.[Uid] = CAST(alx.AddedUserUid AS uniqueidentifier) 
    INNER JOIN [Tenant] AS t ON alx.TenantId = t.Id
    INNER JOIN [Subscription] AS s ON s.TenantId = t.id
UNION ALL
    SELECT al.[AuditLogId], --- DETTACHUSERS
        al.[OperationCode], al.[Operation], al.[Table], al.[RowId], al.[Timestamp], al.[UserUid], al.[UserName], 
        al.[IpAddress], al.[OperationSet], al.[ContextUid], 'User' AS [Field], null, u.[FirstName] + ' ' + u.[LastName], s.Id
    FROM [auditlogs] AS al
    INNER JOIN (
        SELECT TOP 1 * 
        FROM (
            SELECT [AuditLogId],
                [OperationCode], [Operation], [Table], [RowId], [Timestamp], [UserUid], [UserName], 
                [IpAddress], [OperationSet], [ContextUid],
                MAX(case when [Field] = 'UserUid' then [NewValue] end) AS AddedUserUid,
                MAX(case when [Field] = 'TenantId' then [NewValue] end) TenantId
            FROM [auditlogs] AS al
            WHERE al.[Table] = 'TenantUser' AND OperationCode = 0
            GROUP BY [AuditLogId], [OperationCode], [Operation], [Table], [RowId], [Timestamp], al.[UserUid], [UserName], 
                [IpAddress], [OperationSet], [ContextUid]
        ) AS added
        ORDER BY [Timestamp] DESC
    ) AS alx ON alx.RowId = al.RowId AND al.OperationCode = 2
    INNER JOIN [User] AS u ON u.[Uid] = CAST(alx.AddedUserUid AS uniqueidentifier) 
    INNER JOIN [Tenant] AS t ON alx.TenantId = t.Id
    INNER JOIN [Subscription] AS s ON s.TenantId = t.id

私のビューは他の人が作成できることを知っています。つまり、ビューを再利用してセクションの重複を避けるために、ビューをいくつかの小さなビューに分割します。しかし、それがそれを行うための良い方法であるかどうか、または別のより良い方法があるかどうかを知りたいです。

それを分割して、それは最良の解決策ですか?

4

1 に答える 1

0

CTE は、クエリ内のコードをリファクタリングするための非常に優れた方法です。

1 つだけ注意してください: これはパフォーマンスには影響しません。SQL Server は、(私の意見では) 良くも悪くも、各参照を個別に最適化します。これは Microsoft の既知の問題であり、Microsoft はそれに関するホワイト ペーパーを作成しています。 たとえば、ここでは、この最適化に対する正式な要求を示します。

2 番目のコメントとして、テーブルをそれ自体の要約に結合する場合は、ウィンドウ関数の方が効率的です。あなたのクエリはかなり複雑なので、これが役立つかどうかはわかりません.

はい、複数の cte を持つことができます。以下に基本的な例を示します。

with digits as (select 0 as digit union all select 1 as digit),
     digits2 as (select d1.digit + d2.digit*10 as num from digits d1 cross join digits d2)
select *
from digits2

ちなみに、これは SQL Server で数列を生成するために使用できるのと同じ考え方です。

于 2013-01-18T18:43:21.287 に答える