替换Union和子查询以创建Indexed视图的替代方法

时间:2014-07-15 14:09:46

标签: sql-server indexed-view

当我在SQL Server上运行此查询以创建索引视图时,会发生错误以删除子查询和联盟

CREATE VIEW [dbo].[view_ToolGroup] 
WITH SCHEMABINDING
AS
   SELECT 
      toolGroup.ToolGroupId,toolGroupToTool.ToolId, toolGroupApp.AppId as TGAppId,
      purposeToToolGroup.PurposeId as TGPurposeId, TGRole.RoleId as TGRoleId
   FROM
      [dbo].[toolGroup], [dbo].[purposeToTG], [dbo].[toolGroupToTool],
      [dbo].[toolGroupToeApp] as toolGroupApp,
      [dbo].[toolGroupToeAppToeRole] as toolGroupAppRole,
      [dbo].[eRole] as TGRole    
   WHERE 
      toolGroup.ToolGroupId = purposeToToolGroup.ToolGroupId
      and toolGroup.ToolGroupId = toolGroupToTool.ToolGroupId
      and toolGroup.ToolGroupId = toolGroupApp.ToolGroupId 
      and toolGroupApp.toolGroupToeApplicationID=toolGroupAppRole.toolGroupToeApplicationID
      and toolGroupAppRole.ToolgroupToeApplicationID in 
                   (select ToolgroupToeApplicationID     
                    from [dbo].[ToolgroupToeApplication])   
      and toolGroupAppRole.RoleId = TGRole.RoleId   

   UNION

   SELECT
       toolGroup.ToolGroupId, toolGroup.ToolGroupName,
       null, null, null, null, null, null, null, null
   FROM
       [dbo].[toolGroup], [dbo].[toolGroupToeApplication]
   WHERE 
       toolGroup.ToolGroupId = toolGroupToeApplication.ToolGroupId
       and toolGroup.ToolGroupId not in 
              (select PurposeToToolGroup.ToolGroupId from [dbo].[PurposeToToolGroup])
       and toolGroup.ToolGroupId in (select distinct ToolGroupId 
                                     from [dbo]. [toolGroupToeApplication] )'
GO

CREATE UNIQUE CLUSTERED INDEX IDX_view_ToolGroup
ON view_ToolGroup(ToolGroupId, ToolId, TGPurposeId, TGRoleId)
GO

有人可以提出替代UNION和子查询的替代解决方案吗?

1 个答案:

答案 0 :(得分:2)

根据上述所有建议,没有直接的方法可以做到这一点。但是我们可以作弊。您可以执行以下操作

  1. 将陈述分为两个视图
  2. 为每个视图添加索引
  3. 将IN替换为INNER JOIN
  4. 用户在调用视图时不输入
  5. 正如Damien所说,由于我们不知道这些表格代表什么,因此我尝试建议或试图判断逻辑是愚蠢的。然而,我按照上面的内容重新构建了代码,您可以将其用作模板来构建实际查询。

    希望这有帮助

    --Drop Index If Already Aresent
    IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vw_ToolGroup_One]'))
    DROP VIEW dbo.vw_ToolGroup_One
    GO
    
    IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vw_ToolGroup_Two]'))
    DROP VIEW dbo.vw_ToolGroup_Two
    GO
    
    --Drop Dependant Tables
    IF OBJECT_ID(N'toolGroup_tmp')>0
    BEGIN
        DROP TABLE toolGroup_tmp
    END
    CREATE TABLE toolGroup_tmp (ToolGroupId INT,ToolGroupName VARCHAR(100))
    INSERT INTO toolGroup_tmp
    SELECT 1,'ONE'
    GO
    
    IF OBJECT_ID(N'purposeToTG_tmp')>0
    BEGIN
        DROP TABLE purposeToTG_tmp
    END
    CREATE TABLE purposeToTG_tmp (ToolGroupId INT,PurposeId int)
    INSERT INTO purposeToTG_tmp
    SELECT 1,1
    GO
    
    IF OBJECT_ID(N'toolGroupToTool_tmp')>0
    BEGIN
        DROP TABLE toolGroupToTool_tmp
    END
    CREATE TABLE toolGroupToTool_tmp (ToolGroupId INT,ToolId INT)
    INSERT INTO toolGroupToTool_tmp
    SELECT 1,1
    GO
    
    IF OBJECT_ID(N'toolGroupToeApp_tmp')>0
    BEGIN
        DROP TABLE toolGroupToeApp_tmp
    END
    CREATE TABLE toolGroupToeApp_tmp (ToolGroupId INT,AppId INT,toolGroupToeApplicationID INT)
    INSERT INTO toolGroupToeApp_tmp
    SELECT 1,1,1
    GO
    
    IF OBJECT_ID(N'toolGroupToeAppToeRole_tmp')>0
    BEGIN
        DROP TABLE toolGroupToeAppToeRole_tmp
    END
    CREATE TABLE toolGroupToeAppToeRole_tmp (ToolGroupId INT,RoleId INT,toolGroupToeApplicationID INT)
    INSERT INTO toolGroupToeAppToeRole_tmp
    SELECT 1,1,1 
    GO
    
    IF OBJECT_ID(N'ToolgroupToeApplication_tmp')>0
    BEGIN
        DROP TABLE ToolgroupToeApplication_tmp
    END
    CREATE TABLE ToolgroupToeApplication_tmp (ToolGroupId INT,ToolgroupToeApplicationID INT)
    INSERT INTO ToolgroupToeApplication_tmp
    SELECT 1,1
    GO
    
    IF OBJECT_ID(N'PurposeToToolGroup_tmp')>0
    BEGIN
        DROP TABLE PurposeToToolGroup_tmp
    END
    CREATE TABLE PurposeToToolGroup_tmp (ToolGroupId INT)
    INSERT INTO PurposeToToolGroup_tmp
    SELECT 1
    GO
    
    IF OBJECT_ID(N'eRole_tmp')>0
    BEGIN
        DROP TABLE eRole_tmp
    END
    CREATE TABLE eRole_tmp (RoleId INT)
    INSERT INTO eRole_tmp
    SELECT 1
    GO
    
    --Create Views
    DECLARE @SQL NVARCHAR(MAX)
    
    SET @SQL = '
    CREATE VIEW dbo.vw_ToolGroup_One WITH SCHEMABINDING
    AS
        SELECT
               tg.ToolGroupId,
               tg.ToolGroupName,
               tgtt.ToolId,
               tga.AppId AS TGAppId,
               pttg.PurposeId AS TGPurposeId,
               tgr.RoleId AS TGRoleId
        FROM dbo.toolGroup_tmp tg
             INNER JOIN dbo.purposeToTG_tmp pttg
                 ON tg.ToolGroupId = pttg.ToolGroupId
             INNER JOIN dbo.toolGroupToTool_tmp tgtt
                 ON tg.ToolGroupId = tgtt.ToolGroupId
             INNER JOIN dbo.toolGroupToeApp_tmp tga
                 ON tg.ToolGroupId = tga.ToolGroupId
             INNER JOIN dbo.toolGroupToeAppToeRole_tmp tgar
                 ON tga.toolGroupToeApplicationID = tgar.toolGroupToeApplicationID
             INNER JOIN dbo.ToolgroupToeApplication_tmp tgta
                 ON tgta.ToolgroupToeApplicationID = tgar.ToolgroupToeApplicationID
             INNER JOIN dbo.eRole_tmp tgr
                 ON tgar.RoleId = tgr.RoleId
    '
    EXEC SP_EXECUTESQL @SQL
    
    SET @SQL = '
    CREATE VIEW dbo.vw_ToolGroup_Two WITH SCHEMABINDING
    AS
    
        SELECT tg.ToolGroupId,
               tg.ToolGroupName,
               NULL AS ToolId,
               NULL AS TGAppId,
               NULL AS TGPurposeId,
               NULL AS TGRoleId
        FROM dbo.toolGroup_tmp tg
             INNER JOIN dbo.ToolgroupToeApplication_tmp tgtea
                 ON tg.ToolGroupId = tgtea.ToolGroupId
    '
    EXEC SP_EXECUTESQL @SQL
    
    -- Create Indexes
    CREATE UNIQUE CLUSTERED INDEX IDX_view_ToolGroup_One
    ON vw_ToolGroup_One(ToolGroupId, ToolGroupName, ToolId, TGPurposeId, TGRoleId);
    
    CREATE UNIQUE CLUSTERED INDEX IDX_view_ToolGroup_Two
    ON vw_ToolGroup_Two(ToolGroupId, ToolGroupName);
    
    GO
    
    -- Invoke Query
    SELECT * FROM vw_ToolGroup_One
    UNION ALL
    SELECT * FROM vw_ToolGroup_Two tgt
    WHERE NOT EXISTS (  SELECT 1 
                        FROM dbo.PurposeToToolGroup_tmp pttg 
                        WHERE pttg.ToolGroupId = tgt.ToolGroupId)