2013-01-18 51 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