2017-04-20 6 views
2

私は1億以上の行を照会し、実行を終了するのに10〜15分かかるビューを持っており、クラスター索引付けを提供して物理的に存在するようにしたいスキーマを作成し、読み込む時間が少なくて済みますが、クラスター索引付けを行うためにいくつかの制約があります。つまり、INNER JOINのみが許可され、ビューにはサブクエリーは存在しません。definationこのビューのLEFT JOINをINNER JOINこのビュー定義からサブクエリを排除してクラスタ索引付けを適用できるようにするにはどうすればよいでしょうか。SQL Server 2012のビューにクラスター索引付けを適用する

CREATE view [dbo].[FTM_ProfileDetailsView] with SCHEMABINDING as 

    select FTM.Id 
    , FTM.EmployeeId 
    , FTM.CustomerId 
    , FTM.AbsenceFirstDate 
    , FTM.BackgroundHistory 
    , FTM.BackgroundHistoryComments 
    , FTM.IsEmployeeAbsent,FTM.ServiceId 
    , Case When isnull(FTM.IsSelfManagement,'')='' THEN cast(0 as bit) ELSE FTM.IsSelfManagement END as IsSelfManagement 
    , PR.ServiceLineId,FTM.ProfileId,PR.StatusId,Status.Status as StatusName 
    , PR.ReasonID 
    , PR.ModifiedDate 
    , PR.WithdrawnReason 
    , PR.CreatedBy 
    , PR.CreatedDate 
    , PR.IsActive 
    , mgrs.usernames as LineManagers 
    , cust.CustomerName 
    , ltrim(rtrim(emp.EmployeeTitle+' '+ emp.FirstName+' '+ emp.Surname)) as EmployeeFullName 
    , FTM.ProfileManagerId 
    , FTM.IsProfileManagement 
    , AM.MonitoringChecks 
    , AM.Frequency 
    , AM.ProfileManagerNotes 
    , AM.TaskDateAndTime 
    , FTM.ProfileManagementCriteriaId 
    ,cast(case when PR.StatusId = 13 then 1 else 0 end as bit) as IsActiveMonitoring 
    , CustServ.CustomerServiceName 
    , BU.Name as BusinessUnit 
    , emp.DASID 
    , emp.DateOfBirth as EmployeeDOB 
    , addr.PostCode 
    , coninfo.Email 
    , (select top 1 
     StatusId from dbo.PR_Profileintervention ProfileInt 
     where ProfileInt.ProfileId=FTM.Profileid 
     order by ProfileInt.Id desc) as LatestInterventionStatusId 
    , (select name from dbo.FTM_Intervention Intr 
     where Intr.Id=(select top 1 InterventionId from dbo.PR_Profileintervention ProfileInt 
     where ProfileInt.ProfileId=FTM.Profileid 
     order by ProfileInt.Id desc)) 
     as LatestInterventionName from FTM_Profile FTM 

    LEFT JOIN dbo.ProfileManagersView mgrs ON mgrs.ProfileID = FTM.ProfileID 
    INNER JOIN dbo.Customer cust on cust.Id= FTM.CustomerId 
    INNER JOIN dbo.Employee emp on emp.Id = FTM.EmployeeId 
    INNER JOIN dbo.PR_Profile PR on PR.Profileid=FTM.ProfileId 
    LEFT JOIN dbo.BusinessUnit BU on BU.Id=PR.BUId 
    LEFT JOIN dbo.PR_dv_Status [Status] on [Status].Id = PR.StatusId 
    LEFT JOIN dbo.CM_ActiveMonitoringDetails AM on AM.ProfileId = PR.Profileid 
    LEFT JOIN dbo.FTM_CustomerServiceMapping CustServ on CustServ.ServiceId = FTM.ServiceId and CustServ.CustomerId = FTM.CustomerId 
    LEFT JOIN dbo.contact con on con.Id = emp.ContactID 
    LEFT JOIN dbo.address addr on addr.Id = con.HomeAddressId 
    LEFT JOIN dbo.contactinfo coninfo on coninfo.Id = con.ContactInfoId 
+0

(https://docs.microsoft.com/en-us/sql/relational-databases/views/create-indexed-views) –

+0

[ここからスタート] @ ZoharPeled私はそれを読んだ、私の問題はどのように私の意見definationでこれらの制限を克服することです。 –

+0

これらの制限を克服するために、「Y」にはスイッチ「X」を、また「Z」には「W」をスイッチするという魔法はありません。もしあれば、*なぜあなたは自動的にあなたのためにそれらをしないでしょうか?一般的に、元のクエリが適切に構成されていても制限に達している場合は、クエリの正常な書き換えによって同じまたは他の制限が適用されます。 –

答えて

1

私は提案があります。 SELECTのサブクエリがCROSS APPLYに置かれるようにクエリを変更してみることはできますか?

だからあなたの句にこの線に沿って何か:

CROSS APPLY ( 
       select top 1 StatusId AS LatestInterventionStatusId 
       from dbo.PR_Profileintervention ProfileInt 
       where ProfileInt.ProfileId=FTM.Profileid 
       order by ProfileInt.Id desc 

      ) LatestInterventionStatusId 

CROSS APPLY (
       select name AS LatestInterventionName 
       from dbo.FTM_Intervention Intr 
       where Intr.Id=(select top 1 InterventionId 
           from dbo.PR_Profileintervention ProfileInt 
           where ProfileInt.ProfileId=FTM.Profileid 
           order by ProfileInt.Id desc) 
      )LatestInterventionName 

そしてもちろん、このような何かにSELECTの列名を変更します。

, LatestInterventionStatusId.LatestInterventionStatusId 
, LatestInterventionName.LatestInterventionName 

がこれを与える行きますそれが違うかどうか私に知らせてください。

0

[OK]を私の質問に答えてくれませんでしたが、サブクエリを変更する必要があります。この代わりに、2つのサブクエリを使用してみてください:

/* 
... 
, emp.DateOfBirth as EmployeeDOB 
, addr.PostCode 
, coninfo.Email 
*/ 
, p.StatusId as LatestInterventionStatusId 
, p.name  as LatestInterventionName 

from FTM_Profile FTM 

OUTER APPLY (
    select TOP 1 Intr.name, ProfileInt.StatusId 
    from dbo.PR_Profileintervention ProfileInt 
     LEFT JOIN dbo.FTM_Intervention Intr ON Intr.Id = ProfileInt.InterventionId 
    where ProfileInt.ProfileId = FTM.Profileid 
    order by ProfileInt.Id desc 
) p 
/* 
LEFT JOIN dbo.ProfileManagersView mgrs ON mgrs.ProfileID = FTM.ProfileID 
INNER JOIN dbo.Customer cust on cust.Id= FTM.CustomerId 
INNER JOIN dbo.Employee emp on emp.Id = FTM.EmployeeId 
... 
*/ 
関連する問題