如何优化T-SQL查询

Vij*_*dra 5 t-sql sql-server asp.net

我正在编写一个T-SQL查询,我正在开发电子商务网站,因为我使用了4个主要表:

  1. 产品分类
  2. 产品
  3. 的OrderLineItem
  4. 订购

我在管理部分有一个页面用于管理订单,现在我想过滤ProductCategoryie Order包含Product(我productIdOrderLineItem表中)与所选的相关的ProductCategory,我通过以下查询执行此操作:

SELECT  
    O.OrderID,O.[OrderDate],O.[StatusID]                          
FROM [Order] O                              
INNER JOIN [Dyve_User] U ON U.[UserID] = O.[UserID]                               
INNER JOIN (SELECT OD.OrderID 
            FROM OrderLineItem OD
            LEFT OUTER JOIN [Product] P ON OD.ProductID = P.ProductID
            LEFT OUTER JOIN [ProductCategory] PC ON PC.CategoryID = P.CategoryID
            WHERE 
               (P.CategoryID = COALESCE(@CategoryID, P.CategoryID)                              
                OR P.CategoryID IN (SELECT CategoryID 
                                    FROM ProductCategory                              
                                    WHERE ParentID = COALESCE(@CategoryID, ParentID)
                                   )
               )                              
           ) AS T  ON O.OrderID = T.OrderID  
Run Code Online (Sandbox Code Playgroud)

我的这个查询返回正确的结果,但查询每次都超时,任何人都可以告诉我如何优化这个查询,这样就不会超时吗?

以下是表模式:

CREATE TABLE [dbo].[Order](
[OrderID] [int] IDENTITY(1,1) NOT NULL,
[OrderDate] [datetime] NULL,
[OrderTax] [money] NULL,
[OrderTotal] [money] NULL,
[ShippingCharge] [money] NULL,
[TrackingNumber] [varchar](50) NULL,
[TransactionStatusID] [int] NULL,
[UserID] [int] NULL,
[PromotionCode] [varchar](50) NULL
[ExpiryDate] [datetime] NULL,
[PaymentType] [tinyint] NULL
  CONSTRAINT [Order_PK] PRIMARY KEY CLUSTERED 
  (
[OrderID] ASC
 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,          ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  ) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

产品表:

CREATE TABLE [dbo].[Product](
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[CategoryID] [int] NULL,
[ProductName] [nvarchar](600) NULL,
[ManufacturerID] [int] NULL,
[UnitPrice] [money] NULL,
[RetailPrice] [money] NULL,
[IsOnSale] [bit] NOT NULL,
[ExpiryDate] [datetime] NULL,
[IsElectrical] [bit] NULL,
[IsActive] [bit] NULL,
[ProductType] [int] NULL,
[AllowBackOrder] [bit] NULL
   CONSTRAINT [Product_PK] PRIMARY KEY CLUSTERED 
   (
[ProductID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,        ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
   ) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

ProductCategory表:

CREATE TABLE [dbo].[ProductCategory](
[CategoryID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[Description] [nvarchar](max) NULL,
[ParentID] [int] NULL,
[IsActive] [bit] NULL
    CONSTRAINT [ProductCategory_PK] PRIMARY KEY CLUSTERED 
   (
[CategoryID] ASC
   )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,        ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  ) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

OrderLineItem表:

CREATE TABLE [dbo].[OrderLineItem](
[OrderDetailID] [int] IDENTITY(1,1) NOT NULL,
[OrderID] [int] NOT NULL,
[ProductID] [int] NOT NULL
[TotalPrice] [money] NULL,
[Quantity] [int] NULL,
[Discount] [money] NULL,
[UnitPrice] [money] NULL,
[UserID] [int] NULL,
    CONSTRAINT [OrderLineItem_PK] PRIMARY KEY CLUSTERED 
      (
[OrderDetailID] ASC
   )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,        ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
   ) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 0

这尚未经过测试,因此我不确定它是否仍然符合您对查询的预期。

它将获取Orders 的 s 具有OrderLineItemProducta 且 aCategoryID等于@CategoryID或 的子类别@CategoryID

SELECT O.OrderID,
       O.[OrderDate],
       O.[StatusID]
FROM   [Order] AS O
WHERE  O.OrderID IN (SELECT OD.OrderID
                     FROM   OrderLineItem AS OD
                            INNER JOIN Product AS P
                              ON OD.ProductID = P.ProductID
                            INNER JOIN (SELECT PC.CategoryID
                                        FROM   ProductCategory
                                        WHERE  ParentID = @CategoryID
                                        UNION ALL
                                        SELECT @CategoryID) AS C
                              ON P.CategoryID = C.CategoryID)
Run Code Online (Sandbox Code Playgroud)

至于性能,你只需要测试一下就知道了。

索引是一件好事,您应该确保外键列上有索引。