Sql server 如果某些参数未传递给过程,则参数化存储过程将绕过左联接

Sql server 如果某些参数未传递给过程,则参数化存储过程将绕过左联接,sql-server,tsql,stored-procedures,conditional-statements,left-join,Sql Server,Tsql,Stored Procedures,Conditional Statements,Left Join,我已经在存储过程中添加了一个左连接,但是现在,即使我没有传递连接所需的参数,我的查询也要花费4到10倍的时间才能运行 以下是我的存储过程: USE [Test] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[OrderLoadAllPaged] @OrderId int = 0, @WarehouseId int = 0, @PaymentMethodSystemNam

我已经在存储过程中添加了一个左连接,但是现在,即使我没有传递连接所需的参数,我的查询也要花费4到10倍的时间才能运行

以下是我的存储过程:

USE [Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[OrderLoadAllPaged]
    @OrderId int = 0,
    @WarehouseId int = 0,
    @PaymentMethodSystemName nvarchar(max) = null,
    @OrderStatusId int = 0,
    @PaymentStatusId int = 0,
    @ShippingStatusId int = 0,
    @BillingEmail nvarchar(max) = null,
    @BillingFirstName nvarchar(max) = null,
    @BillingLastName nvarchar(max) = null,
    @ShippingMethod nvarchar(max) = null,
    @CreatedFromUtc datetime = null,
    @CreatedToUtc datetime = null
AS
BEGIN
    DECLARE
        @sql nvarchar(max)

    SET NOCOUNT ON;

    SELECT TOP 100 *
    FROM [Test].[dbo].[Order] o with (NOLOCK)

    LEFT join [Test].[dbo].[Address] a on (a.Id LIKE o.BillingAddressId)
    WHERE (@BillingEmail IS null OR a.[Email] = @BillingEmail)
    AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
    AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)

    AND
        o.[Deleted] = 0

    AND (o.[Id] = @OrderId OR @OrderId = 0)
    AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)

    AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)

    AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
    AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
    AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)

    AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)
    AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
    AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')

    ORDER BY o.[CreatedOnUtc] DESC
END
如果
@BillingEmail
@BillingFirstName
@BillingLastName
都为空,我如何能够一起绕过该查询

我想可能是这样,但这不对:

case
    when (ISNULL(@BillingEmail) OR ISNULL(@BillingFirstName) OR ISNULL(@BillingLastName))
    then 
        WHERE
            o.[Deleted] = 0
    ELSE
        LEFT join [Test].[dbo].[Address] a on (a.Id LIKE o.BillingAddressId)
        WHERE (@BillingEmail IS null OR a.[Email] = @BillingEmail) --LIKE '%' + @BillingEmail + '%'
        AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
        AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)
        AND
            o.[Deleted] = 0
end
我查看了索引,但我认为我无法为这3个参数创建索引。
有什么想法可以绕过左连接吗?

让我们尝试在已过滤的
子查询中移动
左连接表

left join 
    (select * from [Test].[dbo].[Address] a 
        where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
        AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
        AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) t1
        ON t1.Id = o.BillingAddressId
要根据您的条件绕过左连接,可以使用以下代码

if (ISNULL(@BillingEmail, '') = '' and ISNULL(@BillingFirstName, '') = '' and ISNULL(@BillingLastName, '') = '')
    begin
        SELECT TOP 100 *
        FROM [Test].[dbo].[Order] o with (NOLOCK)
        WHERE o.[Deleted] = 0
        AND (o.[Id] = @OrderId OR @OrderId = 0)
        AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)
        AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)
        AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
        AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
        AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)
        AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)
        AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
        AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
        ORDER BY o.[CreatedOnUtc] DESC
    end
else
    begin   
        SELECT TOP 100 *
        FROM [Test].[dbo].[Order] o with (NOLOCK)
         left join 
            (select * from [Test].[dbo].[Address] a 
                where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
                AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
                AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) t1
                ON t1.Id = o.BillingAddressId
        WHERE o.[Deleted] = 0
        AND (o.[Id] = @OrderId OR @OrderId = 0)
        AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)
        AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)
        AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
        AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
        AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)

        AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)
        AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
        AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')

        ORDER BY o.[CreatedOnUtc] DESC
    end
if(ISNULL(@BillingEmail,”)=''和ISNULL(@BillingFirstName,”)=''和ISNULL(@BillingLastName,”)='')
开始
选择前100名*
从[Test].[dbo].[Order]o到(NOLOCK)
其中o.[已删除]=0
和(o.[Id]=@OrderId或@OrderId=0)
和(o.[WarehouseId]=@WarehouseId或@WarehouseId=0)
和(@PaymentMethodSystemName为null或o.[PaymentMethodSystemName]=@PaymentMethodSystemName)
和(o.[OrderStatusId]=@OrderStatusId或@OrderStatusId=0)
和(o.[PaymentStatusId]=@PaymentStatusId或@PaymentStatusId=0)
和(o.[ShippingStatusId]=@ShippingStatusId或@ShippingStatusId=0)
和(@ShippingMethod为null或o.[ShippingMethod]=@ShippingMethod)
和o.[CreatedOnUtc]>=ISNULL(@CreatedFromUtc,'1/1/1900')
和o.[CreatedOnUtc]=ISNULL(@CreatedFromUtc,'1/1/1900')
和o.[CreatedOnUtc]
让我们尝试在已筛选的
子查询
中移动
左联接

left join 
    (select * from [Test].[dbo].[Address] a 
        where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
        AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
        AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) t1
        ON t1.Id = o.BillingAddressId
要根据您的条件绕过左连接,可以使用以下代码

if (ISNULL(@BillingEmail, '') = '' and ISNULL(@BillingFirstName, '') = '' and ISNULL(@BillingLastName, '') = '')
    begin
        SELECT TOP 100 *
        FROM [Test].[dbo].[Order] o with (NOLOCK)
        WHERE o.[Deleted] = 0
        AND (o.[Id] = @OrderId OR @OrderId = 0)
        AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)
        AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)
        AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
        AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
        AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)
        AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)
        AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
        AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
        ORDER BY o.[CreatedOnUtc] DESC
    end
else
    begin   
        SELECT TOP 100 *
        FROM [Test].[dbo].[Order] o with (NOLOCK)
         left join 
            (select * from [Test].[dbo].[Address] a 
                where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
                AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
                AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) t1
                ON t1.Id = o.BillingAddressId
        WHERE o.[Deleted] = 0
        AND (o.[Id] = @OrderId OR @OrderId = 0)
        AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)
        AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)
        AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
        AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
        AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)

        AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)
        AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
        AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')

        ORDER BY o.[CreatedOnUtc] DESC
    end
if(ISNULL(@BillingEmail,”)=''和ISNULL(@BillingFirstName,”)=''和ISNULL(@BillingLastName,”)='')
开始
选择前100名*
从[Test].[dbo].[Order]o到(NOLOCK)
其中o.[已删除]=0
和(o.[Id]=@OrderId或@OrderId=0)
和(o.[WarehouseId]=@WarehouseId或@WarehouseId=0)
和(@PaymentMethodSystemName为null或o.[PaymentMethodSystemName]=@PaymentMethodSystemName)
和(o.[OrderStatusId]=@OrderStatusId或@OrderStatusId=0)
和(o.[PaymentStatusId]=@PaymentStatusId或@PaymentStatusId=0)
和(o.[ShippingStatusId]=@ShippingStatusId或@ShippingStatusId=0)
和(@ShippingMethod为null或o.[ShippingMethod]=@ShippingMethod)
和o.[CreatedOnUtc]>=ISNULL(@CreatedFromUtc,'1/1/1900')
和o.[CreatedOnUtc]=ISNULL(@CreatedFromUtc,'1/1/1900')
和o.[CreatedOnUtc]
作为替代方案,您可以将其作为单个查询保存,如下所示:

SELECT TOP 100 *
FROM [Test].[dbo].[Order] o with (NOLOCK)

LEFT join [Test].[dbo].[Address] a on a.Id = o.BillingAddressId and (
    coalesce(@BillingEmail,'') <> ''
    or coalesce(@BillingFirstName,'') <> ''
    or coalesce(@BillingLastName,'') <> ''
  )

WHERE (@BillingEmail IS null OR a.[Email] = @BillingEmail)
AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)
选择前100名*
从[Test].[dbo].[Order]o到(NOLOCK)
左连接[Test].[dbo].[Address]a,在a.Id=o.billingaddress和(
合并(@BillingEmail,)“”
或合并(@BillingFirstName,)”
或合并(@BillingLastName,)”
)
其中(@BillingEmail为空或[Email]=@BillingEmail)
和(@BillingFirstName为null或a.[FirstName]=@BillingFirstName)
和(@BillingLastName为null或a.[LastName]=@BillingLastName)

注意:仅当其中一个计费变量具有值时才尝试联接。

作为替代方法,您可以将其作为单个查询保留,如下所示:

SELECT TOP 100 *
FROM [Test].[dbo].[Order] o with (NOLOCK)

LEFT join [Test].[dbo].[Address] a on a.Id = o.BillingAddressId and (
    coalesce(@BillingEmail,'') <> ''
    or coalesce(@BillingFirstName,'') <> ''
    or coalesce(@BillingLastName,'') <> ''
  )

WHERE (@BillingEmail IS null OR a.[Email] = @BillingEmail)
AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)
选择前100名*
来自[测试][dbo]