sql-server-2012subqueryindexed-view

Not able to create index on schema binding view


Not able to create index on below schema binding view.It is created from another view (v_prod_manu_sub).It is showing below error message:

Cannot create index on view "dbo.V_PROD_MANU" because it references derived table "X" (defined by SELECT statement in FROM clause). Consider removing the reference to the derived table or not indexing the view.

How to change this below query for index creation ?

ALTER VIEW [dbo].[V_PROD_MANU] WITH SCHEMABINDING AS
SELECT X.PRODUCT, CAST(RIGHT(TEXT_CODE,LEN(F_TEXT_CODE)-1) AS VARCHAR(30)) AS TEXT_CODE,
    CAST(SUBSTRING(RIGHT(PHRASE,LEN(F_PHRASES)-1),9,LEN(F_PHRASE)-3) AS varchar(700)) AS PHRASE
    FROM (
    SELECT V1.PRODUCT,
    (SELECT ',' + V2.TEXT_CODE FROM dbo.V_PROD_MANU_SUB V2 WHERE V1.PRODUCT = V2.PRODUCT ORDER BY V2.F_COUNTER  FOR XML PATH('')) AS TEXT_CODE,
    (SELECT ' |par|par ' + V3.F_PHRASE FROM dbo.V_PROD_MANU_SUB V3 WHERE V1.PRODUCT = V3.PRODUCT ORDER BY V3.F_COUNTER FOR XML PATH('')) AS PHRASE
FROM dbo.V_PROD_MANU_SUB  V1 GROUP BY V1.PRODUCT)X

OUTPUT:

Product         TEXT_CODE                PHRASE 
00-021      MANU0043,MANU0050     Inc |par  Pharmaceuticals Group |par  235 East 5nd Street |par usa |par 1-800-123-000

Solution

  • Typically people use STUFF() to remove a leading comma, instead of these messy converts and LEN() calculations. For example:

    SELECT V1.PRODUCT,
        TEXT_CODE = STUFF
        (
          (
            (SELECT ',' + V2.TEXT_CODE 
               FROM dbo.V_PROD_MANU_SUB AS V2 
               WHERE V1.PRODUCT = V2.PRODUCT 
               ORDER BY V2.F_COUNTER  
               FOR XML PATH(''), 
               TYPE).value('./text()[1]','nvarchar(max)')
          ),
        1,1,N'')
    FROM dbo.V_PROD_MANU_SUB AS V1 
    GROUP BY V1.PRODUCT;
    
    -- much easier in SQL Server 2017 with STRING_AGG()
    

    But that doesn't seem to have anything to do with why you need to materialize the comma-separated list in the first place, whether it has a leading comma or not.

    Indexed views are often a form of premature optimization. Essentially you're saying, "the cost of querying this data will be far greater than the cost of maintaining it." Do you know that? How? What is your workload balance (read:write)? How slow is the query now? How often does it run? How long do updates take?

    If you do know that, you will have better luck materializing it to your own table, manually, through a trigger. An indexed view is quite likely going to be a dead end for a variety of reasons.