SQL Server : query simplification - many joins and a giant WHERE section

标签 sql sql-server performance tsql

我正在尝试运行一个存储过程,但它会因使用过多内存而超时。运行它的服务器只有 1.5GB 的内存可以使用。这是原始查询:

CREATE PROCEDURE [dbo].[rpt_Registrations_Std]
    @Action nvarchar(50) = '',  -- Action is field name for now
    @DATE_OPRT_FROM datetime = null,
    @DATE_OPRT_TO datetime = null,
    @DATE_EFFECTIVE_FROM datetime = null,
    @DATE_EFFECTIVE_TO datetime = null,
    @DATE_MODIFIED_FROM datetime = null,
    @DATE_MODIFIED_TO datetime = null,
    @ASSET_NO nvarchar(4000) = '',
    @ASSET_NO_FROM nvarchar(20) = '',
    @ASSET_NO_TO nvarchar(20) = '',
    @HOLDER_CD nvarchar(4000) = '',
    @HOLDER_CD_FROM nvarchar(10) = '',  
    @HOLDER_CD_TO nvarchar(10) = '',    
    @SITE_CD nvarchar(4000) = '',
    @SITE_CD_FROM nvarchar(10) = '',
    @SITE_CD_TO nvarchar(10) = '',
    @ASSETCODE nvarchar(4000) = '',
    @ASSETCODE_FROM nvarchar(10) = null,
    @ASSETCODE_TO nvarchar(10) = null,
    @FUND_CD nvarchar(4000) = '',
    @FUND_CD_FROM nvarchar(10) = '',
    @FUND_CD_TO nvarchar(10) = '',
    @PO_NO nvarchar(4000) = '',
    @PO_NO_FROM nvarchar(15) = '',
    @PO_NO_TO nvarchar(15) = '',
    @STATUS nvarchar(4000) = '',
    @STATUS_FROM int = null,
    @STATUS_TO int = null,
    @UNITPRICE_FROM money = null,
    @UNITPRICE_TO money = null,
    @CAPITALIZED bit = Null
AS
BEGIN
    select cast(data as nvarchar) ASSET_NO INTO #asset_nos from dbo.split(@ASSET_NO,',') 
        where data is not null  
    select cast(data as nvarchar) HOLDER_CD INTO #holders from dbo.split(@HOLDER_CD,',') 
        where data is not null
    select cast(data as nvarchar) SITE_CD INTO #site from dbo.split(@SITE_CD,',') 
        where data is not null
    select cast(data as nvarchar) ASSETCODE INTO #assetcode from dbo.split(@ASSETCODE,',') 
        where data is not null
    select cast(data as nvarchar) FUND_CD INTO #fundcode from dbo.split(@FUND_CD,',') 
        where data is not null
    select cast(data as nvarchar) PO_NO INTO #pono from dbo.split(@PO_NO,',') 
        where data is not null
    select cast(data as int) [STATUS] INTO #status from dbo.split(@STATUS,',') 
        where data is not null


    DECLARE @FIELD nvarchar(20)
    SET @FIELD = @Action

    --- FIELD Def for report From here
    SELECT 
        a.ASSET_NO
        ,a.DATE_RECEIVED as DATE_OPRT
        ,a.DATE_EFFECTIVE_REGISTERED as DATE_EFFECTIVE
        ,a.DATE_REGISTERED as DATE_MODIFIED
        ,a.USER_ID_REGIST as USER_ID_MODIFY
        ,a.DESC_1
        ,a.DESC_2
        ,a.DESC_AX
        ,a.DESC_1  
            + CASE WHEN IsNull(a.DESC_2, '') = '' THEN '' ELSE ' ' + a.DESC_2 END
            + CASE WHEN IsNull(a.DESC_AX, '') = '' THEN '' ELSE ' ' + a.DESC_AX END
            as ASSET_DESC
        ,a.MANUFACTURER
        ,a.MODEL
        ,a.SERIAL_NO
        ,a.WEIGHT
        ,a.ASSETCODE
        ,a.SITE_CD
        ,a.ROOM_CD
        ,a.BUILDING_CD
        ,a.HOLDER_CD            
        ,a.HOLDER_DESC          
        ,a.STATUS
        ,Left(a.STATUS_DESC, 10) as STATUS_DESC
        ,ac.CODE_DESCRIPTION    
        ,a.RM_DESC_1            AS ROOM_DESC
        ,a.SITE_NAME_1          AS SITE_NAME
        ,a.BUILDING_NAME    
        ,a.DATE_RECEIVED
        ,fin.DATE_INSERVICE     
        ,fin.ORIG_COST
        ,fin.QTY
        ,fin.PM_FUND_CD         as FUND_CD
        ,fin.CAPITALIZED
        ,fnd.FUND_DESC
        ,a.PM_PO_NO             as PO_NO

        -- Initial values
        ,u.ORIG_COST            AS INIT_COST
        ,ui.ASSETCODE           AS INIT_ASSETCODE
        ,uR.SITE_CD             AS INIT_SITE_CD
        ,u.ROOM_CD              AS INIT_ROOM_CD
        ,uR.BUILDING_CD         AS INIT_BUILDING_CD
        ,uR.RM_DESC_1           AS INIT_ROOM_DESC
        ,uR.BUILDING_NAME       AS INIT_BUILDING_NAME
        ,uR.SITE_NAME_1         AS INIT_SITE_NAME
        ,u.HOLDER_CD            AS INIT_HOLDER_CD
        ,uH.ORG_DESC            AS INIT_HOLDER_DESC
        ,uac.CODE_DESCRIPTION   AS INIT_CODE_DESCRIPTION

        FROM vAsset as a
        LEFT JOIN vAsset_Rgst_Info as u ON a.ASSET_ID = u.ASSET_ID
        LEFT JOIN tAssetCode    as ac ON a.ASSETCODE = ac.ASSETCODE
        LEFT JOIN tAssetFin     as fin ON a.ASSET_NO = fin.ASSET_NO
        LEFT JOIN tFunding      as fnd ON fin.PM_FUND_CD = fnd.FUND_CD
        LEFT JOIN tItemCatalog  as ui ON u.ITEM_CD = ui.ITEM_CD
        LEFT jOIN tAssetCode    as uac ON ui.ASSETCODE = uac.ASSETCODE
        LEFT JOIN vRoom         as uR ON u.ROOM_CD = uR.ROOM_CD
        LEFT JOIN tOrganization as uH ON u.HOLDER_CD = uH.ORG_CD

        WHERE 
                ( @DATE_OPRT_FROM is null OR a.DATE_RECEIVED >= @DATE_OPRT_FROM )
            AND ( @DATE_OPRT_TO is null OR a.DATE_RECEIVED <= @DATE_OPRT_TO )
            AND ( @DATE_EFFECTIVE_FROM is null OR a.DATE_EFFECTIVE_REGISTERED >= @DATE_EFFECTIVE_FROM )
            AND ( @DATE_EFFECTIVE_TO is null OR a.DATE_EFFECTIVE_REGISTERED <= @DATE_EFFECTIVE_TO )
            AND ( @DATE_MODIFIED_FROM is null OR a.DATE_REGISTERED >= @DATE_MODIFIED_FROM )
            AND ( @DATE_MODIFIED_TO is null OR a.DATE_REGISTERED <= @DATE_MODIFIED_TO )
            AND ( @ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))
            AND ( @ASSET_NO_FROM = '' OR u.ASSET_NO >= @ASSET_NO_FROM )
            AND ( @ASSET_NO_TO = '' OR u.ASSET_NO <= @ASSET_NO_TO )
            AND ( @HOLDER_CD = '' OR a.HOLDER_CD in ( SELECT HOLDER_CD from #holders ))
            AND ( @HOLDER_CD_FROM = '' OR a.HOLDER_CD >= @HOLDER_CD_FROM )
            AND ( @HOLDER_CD_TO = '' OR a.HOLDER_CD <= @HOLDER_CD_TO )
            AND ( @SITE_CD = '' OR a.SITE_CD in ( SELECT SITE_CD from #site ))
            AND ( @SITE_CD_FROM = '' OR a.SITE_CD >= @SITE_CD_FROM )
            AND ( @SITE_CD_TO = '' OR a.SITE_CD <= @SITE_CD_TO )
            AND ( @ASSETCODE = '' OR a.ASSETCODE in ( SELECT ASSETCODE from #assetcode ))
            AND ( @ASSETCODE_FROM is null OR a.ASSETCODE >= @ASSETCODE_FROM )
            AND ( @ASSETCODE_TO is null OR a.ASSETCODE <= @ASSETCODE_TO )
            AND ( @FUND_CD = '' OR PM_FUND_CD in ( SELECT FUND_CD from #fundcode ))
            AND ( @FUND_CD_FROM = '' OR fin.PM_FUND_CD >= @FUND_CD_FROM )
            AND ( @FUND_CD_TO = '' OR fin.PM_FUND_CD <= @FUND_CD_TO )
            AND ( @PO_NO = '' OR a.PM_PO_NO in ( SELECT PO_NO from #pono ))
            AND ( @PO_NO_FROM = '' OR a.PM_PO_NO >= @PO_NO_FROM )
            AND ( @PO_NO_TO = '' OR a.PM_PO_NO <= @PO_NO_TO )
            AND ( @STATUS = '' OR a.STATUS in ( SELECT [STATUS] from #status ))
            AND ( @STATUS_FROM is null OR a.STATUS >= @STATUS_FROM )
            AND ( @STATUS_TO is null OR a.STATUS <= @STATUS_TO )
            AND ( @UNITPRICE_FROM is null OR fin.UNIT_COST >= @UNITPRICE_FROM ) 
            AND ( @UNITPRICE_TO is null OR fin.UNIT_COST <= @UNITPRICE_TO )
            AND ( @CAPITALIZED is null OR  fin.CAPITALIZED = @CAPITALIZED )
END -- proc

我添加了一些子查询来加速它,但它仍然超时:
ALTER PROCEDURE [dbo].[rpt_Registrations_Std]
    @Action nvarchar(50) = '',  -- Action is field name for now
    @DATE_OPRT_FROM datetime = null,
    @DATE_OPRT_TO datetime = null,
    @DATE_EFFECTIVE_FROM datetime = null,
    @DATE_EFFECTIVE_TO datetime = null,
    @DATE_MODIFIED_FROM datetime = null,
    @DATE_MODIFIED_TO datetime = null,
    @ASSET_NO nvarchar(4000) = '',
    @ASSET_NO_FROM nvarchar(20) = '',
    @ASSET_NO_TO nvarchar(20) = '',
    @HOLDER_CD nvarchar(4000) = '',
    @HOLDER_CD_FROM nvarchar(10) = '',  
    @HOLDER_CD_TO nvarchar(10) = '',    
    @SITE_CD nvarchar(4000) = '',
    @SITE_CD_FROM nvarchar(10) = '',
    @SITE_CD_TO nvarchar(10) = '',
    @ASSETCODE nvarchar(4000) = '',
    @ASSETCODE_FROM nvarchar(10) = null,
    @ASSETCODE_TO nvarchar(10) = null,
    @FUND_CD nvarchar(4000) = '',
    @FUND_CD_FROM nvarchar(10) = '',
    @FUND_CD_TO nvarchar(10) = '',
    @PO_NO nvarchar(4000) = '',
    @PO_NO_FROM nvarchar(15) = '',
    @PO_NO_TO nvarchar(15) = '',
    @STATUS nvarchar(4000) = '',
    @STATUS_FROM int = null,
    @STATUS_TO int = null,
    @UNITPRICE_FROM money = null,
    @UNITPRICE_TO money = null,
    @CAPITALIZED bit = Null
AS
BEGIN

    select cast(data as nvarchar) ASSET_NO INTO #asset_nos from dbo.split(@ASSET_NO,',') 
        where data is not null  
    select cast(data as nvarchar) HOLDER_CD INTO #holders from dbo.split(@HOLDER_CD,',') 
        where data is not null
    select cast(data as nvarchar) SITE_CD INTO #site from dbo.split(@SITE_CD,',') 
        where data is not null
    select cast(data as nvarchar) ASSETCODE INTO #assetcode from dbo.split(@ASSETCODE,',') 
        where data is not null
    select cast(data as nvarchar) FUND_CD INTO #fundcode from dbo.split(@FUND_CD,',') 
        where data is not null
    select cast(data as nvarchar) PO_NO INTO #pono from dbo.split(@PO_NO,',') 
        where data is not null
    select cast(data as int) [STATUS] INTO #status from dbo.split(@STATUS,',') 
        where data is not null



    DECLARE @FIELD nvarchar(20)
    SET @FIELD = @Action

    --- FIELD Def for report From here
    SELECT 
        a.ASSET_NO

        ,a.DATE_RECEIVED as DATE_OPRT
        ,a.DATE_EFFECTIVE_REGISTERED as DATE_EFFECTIVE
        ,a.DATE_REGISTERED as DATE_MODIFIED
        ,a.USER_ID_REGIST as USER_ID_MODIFY

        ,a.DESC_1
        ,a.DESC_2
        ,a.DESC_AX
        ,a.DESC_1  
            + CASE WHEN IsNull(a.DESC_2, '') = '' THEN '' ELSE ' ' + a.DESC_2 END
            + CASE WHEN IsNull(a.DESC_AX, '') = '' THEN '' ELSE ' ' + a.DESC_AX END
            as ASSET_DESC
        ,a.MANUFACTURER
        ,a.MODEL
        ,a.SERIAL_NO
        ,a.WEIGHT
        ,a.ASSETCODE
        ,a.SITE_CD
        ,a.ROOM_CD
        ,a.BUILDING_CD
        ,a.HOLDER_CD            
        ,a.HOLDER_DESC          
        ,a.STATUS
        ,Left(a.STATUS_DESC, 10) as STATUS_DESC
        ,ac.CODE_DESCRIPTION    
        ,a.RM_DESC_1            AS ROOM_DESC
        ,a.SITE_NAME_1          AS SITE_NAME
        ,a.BUILDING_NAME    
        ,a.DATE_RECEIVED
        ,fin.DATE_INSERVICE     
        ,fin.ORIG_COST
        ,fin.QTY
        ,fin.PM_FUND_CD         as FUND_CD
        ,fin.CAPITALIZED
        ,fnd.FUND_DESC
        ,a.PM_PO_NO             as PO_NO

        -- Initial values
        ,u.ORIG_COST            AS INIT_COST
        ,ui.ASSETCODE           AS INIT_ASSETCODE
        ,uR.SITE_CD             AS INIT_SITE_CD
        ,u.ROOM_CD              AS INIT_ROOM_CD
        ,uR.BUILDING_CD         AS INIT_BUILDING_CD
        ,uR.RM_DESC_1           AS INIT_ROOM_DESC
        ,uR.BUILDING_NAME       AS INIT_BUILDING_NAME
        ,uR.SITE_NAME_1         AS INIT_SITE_NAME
        ,u.HOLDER_CD            AS INIT_HOLDER_CD
        ,uH.ORG_DESC            AS INIT_HOLDER_DESC
        ,uac.CODE_DESCRIPTION   AS INIT_CODE_DESCRIPTION

        FROM (SELECT  
         a.ASSET_NO
        ,a.ASSET_ID
        ,a.DATE_EFFECTIVE_REGISTERED
        ,a.DATE_REGISTERED
        ,a.USER_ID_REGIST
        ,a.DESC_1
        ,a.DESC_2
        ,a.DESC_AX
        ,a.MANUFACTURER
        ,a.MODEL
        ,a.SERIAL_NO
        ,a.WEIGHT
        ,a.ASSETCODE
        ,a.SITE_CD
        ,a.ROOM_CD
        ,a.BUILDING_CD
        ,a.HOLDER_CD            
        ,a.HOLDER_DESC          
        ,a.STATUS
        ,a.STATUS_DESC
        ,a.RM_DESC_1
        ,a.SITE_NAME_1
        ,a.BUILDING_NAME    
        ,a.DATE_RECEIVED
        ,a.PM_PO_NO

        FROM vAsset as a WHERE ASSET_NO IN (
        SELECT ASSET_NO FROM vAsset as a
                WHERE 
                ( @DATE_OPRT_FROM is null OR a.DATE_RECEIVED >= @DATE_OPRT_FROM )
            AND ( @DATE_OPRT_TO is null OR a.DATE_RECEIVED <= @DATE_OPRT_TO )
            AND ( @DATE_EFFECTIVE_FROM is null OR a.DATE_EFFECTIVE_REGISTERED >= @DATE_EFFECTIVE_FROM )
            AND ( @DATE_EFFECTIVE_TO is null OR a.DATE_EFFECTIVE_REGISTERED <= @DATE_EFFECTIVE_TO )
            AND ( @DATE_MODIFIED_FROM is null OR a.DATE_REGISTERED >= @DATE_MODIFIED_FROM )
            AND ( @DATE_MODIFIED_TO is null OR a.DATE_REGISTERED <= @DATE_MODIFIED_TO )
            AND ( @HOLDER_CD = '' OR a.HOLDER_CD in ( SELECT HOLDER_CD from #holders ))
            AND ( @HOLDER_CD_FROM = '' OR a.HOLDER_CD >= @HOLDER_CD_FROM )
            AND ( @HOLDER_CD_TO = '' OR a.HOLDER_CD <= @HOLDER_CD_TO )
            AND ( @SITE_CD = '' OR a.SITE_CD in ( SELECT SITE_CD from #site ))
            AND ( @SITE_CD_FROM = '' OR a.SITE_CD >= @SITE_CD_FROM )
            AND ( @SITE_CD_TO = '' OR a.SITE_CD <= @SITE_CD_TO )
            AND ( @ASSETCODE = '' OR a.ASSETCODE in ( SELECT ASSETCODE from #assetcode ))
            AND ( @ASSETCODE_FROM is null OR a.ASSETCODE >= @ASSETCODE_FROM )
            AND ( @ASSETCODE_TO is null OR a.ASSETCODE <= @ASSETCODE_TO )
            AND ( @PO_NO = '' OR a.PM_PO_NO in ( SELECT PO_NO from #pono ))
            AND ( @PO_NO_FROM = '' OR a.PM_PO_NO >= @PO_NO_FROM )
            AND ( @PO_NO_TO = '' OR a.PM_PO_NO <= @PO_NO_TO )
            AND ( @STATUS = '' OR a.STATUS in ( SELECT [STATUS] from #status ))
            AND ( @STATUS_FROM is null OR a.STATUS >= @STATUS_FROM )
            AND ( @STATUS_TO is null OR a.STATUS <= @STATUS_TO )
        )) as a
        LEFT JOIN vAsset_Rgst_Info as u ON a.ASSET_ID = u.ASSET_ID
        LEFT JOIN tAssetCode    as ac ON a.ASSETCODE = ac.ASSETCODE
        LEFT JOIN tAssetFin     as fin ON a.ASSET_NO = fin.ASSET_NO
        LEFT JOIN tFunding      as fnd ON fin.PM_FUND_CD = fnd.FUND_CD
        LEFT JOIN tItemCatalog  as ui ON u.ITEM_CD = ui.ITEM_CD
        LEFT jOIN tAssetCode    as uac ON ui.ASSETCODE = uac.ASSETCODE
        LEFT JOIN vRoom         as uR ON u.ROOM_CD = uR.ROOM_CD
        LEFT JOIN tOrganization as uH ON u.HOLDER_CD = uH.ORG_CD

        WHERE 
                ( @ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))
            AND ( @ASSET_NO_FROM = '' OR u.ASSET_NO >= @ASSET_NO_FROM )
            AND ( @ASSET_NO_TO = '' OR u.ASSET_NO <= @ASSET_NO_TO )
            AND ( @FUND_CD = '' OR PM_FUND_CD in ( SELECT FUND_CD from #fundcode ))
            AND ( @FUND_CD_FROM = '' OR fin.PM_FUND_CD >= @FUND_CD_FROM )
            AND ( @FUND_CD_TO = '' OR fin.PM_FUND_CD <= @FUND_CD_TO )
            AND ( @UNITPRICE_FROM is null OR fin.UNIT_COST >= @UNITPRICE_FROM ) 
            AND ( @UNITPRICE_TO is null OR fin.UNIT_COST <= @UNITPRICE_TO )
            AND ( @CAPITALIZED is null OR  fin.CAPITALIZED = @CAPITALIZED )



END -- proc

我现在不知所措。似乎在太小的服务器上处理的数据太多。

最佳答案

修改内容为:

1)创建一个新的标量函数来测试分隔逗号文本中是否存在数据,无需创建#temp表来检查数据是否存在。

    -- test if token exis in delimited comma string, use spli function
    create FUNCTION [dbo].[inList]
    (

          @delimited NVARCHAR(MAX) ,
          @token NVARCHAR(100) 
      ) 
        RETURNS NVARCHAR(100) 
        as
        begin
        declare @retval NVARCHAR(100) 
        select @retval=data from 
         dbo.split(@delimited) t
        where t.data=@token
        return @retval
        end
        go

我们替换 where 条件中的表达式,如下例所示:
    --   AND ( @ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))

修改为:
            AND ( @ASSET_NO = '' OR u.ASSET_NO = dbo.inlist(@ASSET_NO,u.ASSET_NO))

和所有分隔列表相同

2) 由于您使用了许多空参数,因此在执行前重新编译 SP 以获得新的执行计划( WITH RECOMPILE)

3)修改后的代码:
    Alter PROCEDURE [dbo].[rpt_Registrations_Std]
        @Action nvarchar(50) = '',  -- Action is field name for now
        @DATE_OPRT_FROM datetime = null,
        @DATE_OPRT_TO datetime = null,
        @DATE_EFFECTIVE_FROM datetime = null,
        @DATE_EFFECTIVE_TO datetime = null,
        @DATE_MODIFIED_FROM datetime = null,
        @DATE_MODIFIED_TO datetime = null,
        @ASSET_NO nvarchar(4000) = '',
        @ASSET_NO_FROM nvarchar(20) = '',
        @ASSET_NO_TO nvarchar(20) = '',
        @HOLDER_CD nvarchar(4000) = '',
        @HOLDER_CD_FROM nvarchar(10) = '',  
        @HOLDER_CD_TO nvarchar(10) = '',    
        @SITE_CD nvarchar(4000) = '',
        @SITE_CD_FROM nvarchar(10) = '',
        @SITE_CD_TO nvarchar(10) = '',
        @ASSETCODE nvarchar(4000) = '',
        @ASSETCODE_FROM nvarchar(10) = null,
        @ASSETCODE_TO nvarchar(10) = null,
        @FUND_CD nvarchar(4000) = '',
        @FUND_CD_FROM nvarchar(10) = '',
        @FUND_CD_TO nvarchar(10) = '',
        @PO_NO nvarchar(4000) = '',
        @PO_NO_FROM nvarchar(15) = '',
        @PO_NO_TO nvarchar(15) = '',
        @STATUS nvarchar(4000) = '',
        @STATUS_FROM int = null,
        @STATUS_TO int = null,
        @UNITPRICE_FROM money = null,
        @UNITPRICE_TO money = null,
        @CAPITALIZED bit = Null
        -- hint recompile for new fresh execution plan
        WITH RECOMPILE
    AS
    BEGIN
        --select cast(data as nvarchar) ASSET_NO INTO #asset_nos from dbo.split(@ASSET_NO,',') 
        --    where data is not null  
        --select cast(data as nvarchar) HOLDER_CD INTO #holders from dbo.split(@HOLDER_CD,',') 
        --    where data is not null
        --select cast(data as nvarchar) SITE_CD INTO #site from dbo.split(@SITE_CD,',') 
        --    where data is not null
        --select cast(data as nvarchar) ASSETCODE INTO #assetcode from dbo.split(@ASSETCODE,',') 
        --    where data is not null
        --select cast(data as nvarchar) FUND_CD INTO #fundcode from dbo.split(@FUND_CD,',') 
        --    where data is not null
        --select cast(data as nvarchar) PO_NO INTO #pono from dbo.split(@PO_NO,',') 
        --    where data is not null
        --select cast(data as int) [STATUS] INTO #status from dbo.split(@STATUS,',') 
        --    where data is not null


        DECLARE @FIELD nvarchar(20)
        SET @FIELD = @Action

        --- FIELD Def for report From here
        SELECT 
            a.ASSET_NO
            ,a.DATE_RECEIVED as DATE_OPRT
            ,a.DATE_EFFECTIVE_REGISTERED as DATE_EFFECTIVE
            ,a.DATE_REGISTERED as DATE_MODIFIED
            ,a.USER_ID_REGIST as USER_ID_MODIFY
            ,a.DESC_1
            ,a.DESC_2
            ,a.DESC_AX
            ,a.DESC_1  
                + CASE WHEN IsNull(a.DESC_2, '') = '' THEN '' ELSE ' ' + a.DESC_2 END
                + CASE WHEN IsNull(a.DESC_AX, '') = '' THEN '' ELSE ' ' + a.DESC_AX END
                as ASSET_DESC
            ,a.MANUFACTURER
            ,a.MODEL
            ,a.SERIAL_NO
            ,a.WEIGHT
            ,a.ASSETCODE
            ,a.SITE_CD
            ,a.ROOM_CD
            ,a.BUILDING_CD
            ,a.HOLDER_CD            
            ,a.HOLDER_DESC          
            ,a.STATUS
            ,Left(a.STATUS_DESC, 10) as STATUS_DESC
            ,ac.CODE_DESCRIPTION    
            ,a.RM_DESC_1            AS ROOM_DESC
            ,a.SITE_NAME_1          AS SITE_NAME
            ,a.BUILDING_NAME    
            ,a.DATE_RECEIVED
            ,fin.DATE_INSERVICE     
            ,fin.ORIG_COST
            ,fin.QTY
            ,fin.PM_FUND_CD         as FUND_CD
            ,fin.CAPITALIZED
            ,fnd.FUND_DESC
            ,a.PM_PO_NO             as PO_NO

            -- Initial values
            ,u.ORIG_COST            AS INIT_COST
            ,ui.ASSETCODE           AS INIT_ASSETCODE
            ,uR.SITE_CD             AS INIT_SITE_CD
            ,u.ROOM_CD              AS INIT_ROOM_CD
            ,uR.BUILDING_CD         AS INIT_BUILDING_CD
            ,uR.RM_DESC_1           AS INIT_ROOM_DESC
            ,uR.BUILDING_NAME       AS INIT_BUILDING_NAME
            ,uR.SITE_NAME_1         AS INIT_SITE_NAME
            ,u.HOLDER_CD            AS INIT_HOLDER_CD
            ,uH.ORG_DESC            AS INIT_HOLDER_DESC
            ,uac.CODE_DESCRIPTION   AS INIT_CODE_DESCRIPTION

            FROM vAsset as a
            LEFT JOIN vAsset_Rgst_Info as u ON a.ASSET_ID = u.ASSET_ID
            LEFT JOIN tAssetCode    as ac ON a.ASSETCODE = ac.ASSETCODE
            LEFT JOIN tAssetFin     as fin ON a.ASSET_NO = fin.ASSET_NO
            LEFT JOIN tFunding      as fnd ON fin.PM_FUND_CD = fnd.FUND_CD
            LEFT JOIN tItemCatalog  as ui ON u.ITEM_CD = ui.ITEM_CD
            LEFT jOIN tAssetCode    as uac ON ui.ASSETCODE = uac.ASSETCODE
            LEFT JOIN vRoom         as uR ON u.ROOM_CD = uR.ROOM_CD
            LEFT JOIN tOrganization as uH ON u.HOLDER_CD = uH.ORG_CD

            WHERE 
                    ( @DATE_OPRT_FROM is null OR a.DATE_RECEIVED >= @DATE_OPRT_FROM )
                AND ( @DATE_OPRT_TO is null OR a.DATE_RECEIVED <= @DATE_OPRT_TO )
                AND ( @DATE_EFFECTIVE_FROM is null OR a.DATE_EFFECTIVE_REGISTERED >= @DATE_EFFECTIVE_FROM )
                AND ( @DATE_EFFECTIVE_TO is null OR a.DATE_EFFECTIVE_REGISTERED <= @DATE_EFFECTIVE_TO )
                AND ( @DATE_MODIFIED_FROM is null OR a.DATE_REGISTERED >= @DATE_MODIFIED_FROM )
                AND ( @DATE_MODIFIED_TO is null OR a.DATE_REGISTERED <= @DATE_MODIFIED_TO )
             --   AND ( @ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))
                AND ( @ASSET_NO = '' OR u.ASSET_NO = dbo.inlist(@ASSET_NO,u.ASSET_NO))
                AND ( @ASSET_NO_FROM = '' OR u.ASSET_NO >= @ASSET_NO_FROM )
                AND ( @ASSET_NO_TO = '' OR u.ASSET_NO <= @ASSET_NO_TO )
            --    AND ( @HOLDER_CD = '' OR a.HOLDER_CD in ( SELECT HOLDER_CD from #holders ))
                AND ( @HOLDER_CD = '' OR a.HOLDER_CD =dbo.inlist(@HOLDER_CD,a.HOLDER_CD))
                AND ( @HOLDER_CD_FROM = '' OR a.HOLDER_CD >= @HOLDER_CD_FROM )
                AND ( @HOLDER_CD_TO = '' OR a.HOLDER_CD <= @HOLDER_CD_TO )
           --     AND ( @SITE_CD = '' OR a.SITE_CD in ( SELECT SITE_CD from #site ))
                AND ( @SITE_CD = '' OR a.SITE_CD =dbo.inlist(@SITE_CD,a.SITE_CD))
                AND ( @SITE_CD_FROM = '' OR a.SITE_CD >= @SITE_CD_FROM )
                AND ( @SITE_CD_TO = '' OR a.SITE_CD <= @SITE_CD_TO )
              --  AND ( @ASSETCODE = '' OR a.ASSETCODE in ( SELECT ASSETCODE from #assetcode ))
                AND ( @ASSETCODE = '' OR a.ASSETCODE =dbo.inlist(@ASSETCODE,a.ASSETCODE))
                AND ( @ASSETCODE_FROM is null OR a.ASSETCODE >= @ASSETCODE_FROM )
                AND ( @ASSETCODE_TO is null OR a.ASSETCODE <= @ASSETCODE_TO )
                -- PM_FUND_CD qualified by a.PM_FUND_CD
                --AND ( @FUND_CD = '' OR PM_FUND_CD in ( SELECT FUND_CD from #fundcode ))
                AND ( @FUND_CD = '' OR a.PM_FUND_CD  =dbo.inlist(@FUND_CD,a.PM_FUND_CD))

                AND ( @FUND_CD_FROM = '' OR fin.PM_FUND_CD >= @FUND_CD_FROM )
                AND ( @FUND_CD_TO = '' OR fin.PM_FUND_CD <= @FUND_CD_TO )

              --  AND ( @PO_NO = '' OR a.PM_PO_NO in ( SELECT PO_NO from #pono ))
                AND ( @PO_NO = '' OR a.PM_PO_NO =dbo.inlist(@PO_NO,a.PM_PO_NO))
                AND ( @PO_NO_FROM = '' OR a.PM_PO_NO >= @PO_NO_FROM )
                AND ( @PO_NO_TO = '' OR a.PM_PO_NO <= @PO_NO_TO )
             --   AND ( @STATUS = '' OR a.STATUS in ( SELECT [STATUS] from #status ))
                AND ( @STATUS = '' OR a.STATUS =dbo.inlist(@STATUS,a.STATUS))
                AND ( @STATUS_FROM is null OR a.STATUS >= @STATUS_FROM )
                AND ( @STATUS_TO is null OR a.STATUS <= @STATUS_TO )
                AND ( @UNITPRICE_FROM is null OR fin.UNIT_COST >= @UNITPRICE_FROM ) 
                AND ( @UNITPRICE_TO is null OR fin.UNIT_COST <= @UNITPRICE_TO )
                AND ( @CAPITALIZED is null OR  fin.CAPITALIZED = @CAPITALIZED )
    END -- proc
    go

更新:

根据评论,
“您所描述的在存储过程中不起作用,因为参数值事先未知。”

参数值确实是已知的时间头,因为它们是在存储过程头中接收的。标量函数在调用时执行,并根据 SP 传递的参数返回值或 null。

例如:片段代码
    AND ( @ASSETCODE = '' OR a.ASSETCODE =dbo.inlist(@ASSETCODE,a.ASSETCODE))

@ASSETCODE 是一个参数值(分隔列表)
a.ASSETCODE 是当前行的值
所以,这个表达式被及时评估并返回真/假
OP中使用的其他六个列表相同

以下测试用例模拟了我的回答中使用的标量函数 {inlist} 的使用:
    create procedure test_delimeted_list (
    @list1 nvarchar(100)
    )
    as
    begin
    select * from products p
    where p.ProductID = dbo.[inList](@list1,p.productid)
    end
    go

测试 1:列表有一个值
     exec test_delimeted_list '2,500,610'   -- 2  is existing

北风数据库返回数据:
   ProductID    ProductName SupplierID  CategoryID  QuantityPerUnit UnitPrice   UnitsInStock    UnitsOnOrder    ReorderLevel    Discontinued
   2    Chang   1   1   24 - 12 oz bottles  19.00   17  40  25  0

测试 2:列表为空
    exec test_delimeted_list  null

返回数据为空

我希望 OP 测试我的代码并为缺少或不起作用的内容提供评论。

关于SQL Server : query simplification - many joins and a giant WHERE section,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31686927/

相关文章:

sql - 合并复制不适用于非默认冲突解决程序

sql-server - SQL Server 查询使用不同排序规则的两个链接数据库

sql - 表 A 的 PK 被表 B 的 FK 引用。不能丢弃表 A 的 PK

performance - 全文索引缓慢。寻找替代品

SQL 长时间运行的查询/最大化服务器资源,例如内存/中央处理器

c# - 如何在 C# 中将 SQL "Select"结果保存到变量中

mysql - SQL中如何将字符串拆分为单列并排列在同一列中

c# - 使用 linq 更新对象的性能更好

C#:将字符串插入另一个字符串 - 性能问题

SQL Server - 是否需要创建具有唯一约束的索引作为列之一?