3

当我在 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和子查询吗?

4

1 回答 1

3

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

  1. 将语句分成两个视图
  2. 为每个视图添加索引
  3. 将 IN 替换为 INNER JOIN
  4. 调用视图时用户不在

正如 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)
于 2014-07-18T11:30:20.803 回答