2013-01-18 52 views
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 

我知道我的觀點可能被別人組成的,我的意思是,爲了重新使用它們,避免重複的部分在幾個較小的意見分裂它。不過,我想知道這是否是一種好方法,或者如果有另一種更好的方法。

拆分它,這是最好的解決方案嗎?

回答

0

CTE是重構查詢中代碼的一種非常好的方法。

只需謹慎一點:這不會影響性能。 SQL Server仍然分別優化每個引用,無論更好還是更差(在我看來)。這是微軟已知的一個問題,他們甚至寫了白皮書。例如,Here是對此優化的正式請求。

作爲第二條評論,通常當你加入一個表格以得到自己的摘要時,窗口函數會更有效率。您的查詢相當複雜,所以我不確定這是否有幫助。

是的,你可以有多個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中生成數字序列的相同想法。

+0

那麼我的問題是,鑑於我正在使用CTE,我可以有更多的只是在我的情況。我的意思是,我知道我可以有更多的只是一個,但在我的代碼我怎麼能做到這一點?這是沒有必要的一個工作的例子,一種僞代碼是好的。謝謝 – lontivero