Sql server 如果某些参数未传递给过程,则参数化存储过程将绕过左联接
我已经在存储过程中添加了一个左连接,但是现在,即使我没有传递连接所需的参数,我的查询也要花费4到10倍的时间才能运行 以下是我的存储过程: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
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]