在sql中优化查询子查询

时间:2017-04-07 07:17:10

标签: sql sql-server sql-server-2008

我查询了如下产品库存:

<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CreateFolders" Sequence="execute">NOT Installed</SetProperty>

<Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="INSTALLDIR" Name="WinApp"/>
    </Directory>
</Fragment>

此查询返回我想要的数据,并且它在我的桌面上运行正常,但是当我在较低规格的笔记本电脑上部署运行此查询的应用程序时,它非常慢并导致笔记本电脑挂起。我需要一些关于如何优化查询的帮助,或者可能需要更改它以使其更有效...提前感谢

这是我的InvoiceDetails表的数据 This are the data of my InvoiceDetails table

来自我的PurchaseOrderDetails表的数据 Data From my PurchaseOrderDetails table

产品数据表 Data from Products table

4 个答案:

答案 0 :(得分:1)

你能试试吗? (我没有测试就写了,因为你没有发布样本数据也没有创建表)。请检查并作为起点。比较查询和结果的结果,并比较执行计划。 对性能的分析需要“一些”Sql的知识和考虑几件事的能力(例如,有多少行,是否有索引,使用执行计划和统计等等)

SELECT C.PRODUCTID
    ,C.PRODUCTNAME
    ,COALESCE(D.QTY_SOLD,0) AS QTY_SOLD
    ,COALESCE(E.QTY_STOCKS,0) AS QTY_STOCKS
    ,COALESCE(E.QTY_STOCKS,0)-COALESCE(D.QTY_SOLD,0) AS REMAININGSTOCK
FROM PRODUCTS C 
LEFT JOIN (SELECT PRODUCTID, SUM(QTY) AS QTY_SOLD
           FROM INVOICEDETAILS
           GROUP BY PRODUCTID
           ) D ON B.PRODUCTID = D.PRODUCTID
LEFT JOIN (SELECT PRODUCTID,SUM(QTYRECEIVE) AS QTY_STOCKS
           FROM PURCHASEORDERDETAILS
           GROUP BY PRODUCTID
           ) E ON B.PRODUCTID = E.PRODUCTID

答案 1 :(得分:1)

所以我在选择中删除了你的子查询,我不认为这些是必要的。我也在你的连接中移动并给表提供了更好的别名;

SELECT 
    b.ProductID, 
    c.ProductName,
    ISNULL(SUM(id.Qty),0) as Sold, 
    ISNULL(SUM(pod.QtyReceive),0) as Stocks,
    ISNULL(SUM(pod.QtyReceive),0) - ISNULL(SUM(id.Qty),0) as RemainingStock  
FROM PurchaseOrderDetails pod
INNER JOIN Products pr 
    ON pr.ProductID = pod.ProductID  
LEFT JOIN InvoiceDetails id 
    ON id.ProductID = pod.ProductID 
GROUP BY
    pod.ProductID, pr.ProductName  

您已经加入了这两个表,因此您根本不需要选择子查询。我还在ISNULL中包装了SUM,以确保没有NULL错误。

我建议在代码开头使用SET STATISTICS TIME,IO ON(最后使用OFF命令)。然后复制“&#39;消息”中的所有文字。选项卡进入statisticsparser.com。为查询和比较执行此操作,检查总CPU时间和逻辑读取,您希望这些都更低,以获得更好的性能。我打赌你的逻辑读取会因这个新查询而显着下降。

修改

好的,我已根据您的示例数据整理了一个新查询。我只使用了此查询实际需要的字段,因此对于此示例来说更简单。

样本数据

CREATE TABLE #InvoiceDetails (ProductID int, Qty int)
INSERT INTO #InvoiceDetails (ProductID,Qty)
VALUES (3,50),(1,0),(2,1),(1,12),(2,1),(3,1),(1,1),(2,1),(1,1),(2,1)

CREATE TABLE #PurchaseOrderDetails (ProductID int, Qty int)
INSERT INTO #PurchaseOrderDetails (ProductID, Qty)
VALUES (1,100),(2,20),(4,10),(1,12),(5,12),(4,12),(3,12),(2,20),(3,20),(4,20),(5,20)

CREATE TABLE #Products (ProductID int, ProductName varchar(20))
INSERT INTO #Products (ProductID, ProductName)
VALUES (1,'Sample Product'),(2,'DYE INK CYAN'),(3,'test Product 1'),(4,'test Product 2'),(5,'test Product 3'),(1004,'TESTING PRODUCT')

为此,这是原始查询的输出

ProductID   ProductName     Sold    Stocks  RemainingStock
1           Sample Product  14      112     98
2           DYE INK CYAN    4       40      36
3           test Product 1  51      32      -19
4           test Product 2  0       42      42
5           test Product 3  0       32      32

这是我使用的重写查询。注意,SELECT语句中没有子查询,它们应该在连接中。另请注意,由于我们在子查询中进行聚合,因此我们也不需要在外部查询中执行此操作。

SELECT 
    pod.ProductID, 
    pr.ProductName,
    ISNULL(id.Qty,0) as Sold, 
    ISNULL(pod.Qty,0) as Stocks,
    ISNULL(pod.Qty,0) - ISNULL(id.Qty,0) as RemainingStock  
FROM #Products pr
INNER JOIN (SELECT ProductID, SUM(Qty) Qty FROM #PurchaseOrderDetails GROUP BY ProductID) pod
    ON pr.ProductID = pod.ProductID  
LEFT JOIN (SELECT ProductID, SUM(Qty) Qty FROM #InvoiceDetails GROUP BY ProductID) id 
    ON id.ProductID = pr.ProductID 

这是新输出

ProductID   ProductName     Sold    Stocks  RemainingStock
1           Sample Product  14      112     98
2           DYE INK CYAN    4       40      36
3           test Product 1  51      32      -19
4           test Product 2  0       42      42
5           test Product 3  0       32      32

哪个与原始查询相符。

我建议在您的计算机上尝试此查询并查看哪个表现更好,请尝试我之前提到的STATISTICS TIME,IO命令。

答案 2 :(得分:1)

b.ProductID, c.ProductName分组,您可以使用aggregate函数进行计算。 并在表格中创建indexes以提高效果。

Select 
   b.ProductID, c.ProductName,
   SUM(isnull(a.Qty,0)) as Sold, 
   SUM(b.QtyReceive) as Stocks,
   SUM(b.QtyReceive) - SUM(isnull(a.Qty,0))  as RemainingStock  
from 
   PurchaseOrderDetails b
   LEFT JOIN     InvoiceDetails a  on a.ProductID = b.ProductID  
   INNER JOIN     Products c on b.ProductID = c.ProductID  
Group By 
   b.ProductID, c.ProductName  

答案 3 :(得分:0)

查看您的查询,我认为这可能是等效的(或至少我希望是这样):

 Select
    b.ProductID
  , c.ProductName
  , Case When SUM(a.Qty) IS NULL then 0 else SUM(a.Qty) end as sold
  , Case When SUM(b.QtyReceive) IS NULL then 0 else SUM(b.QtyReceive) end  as Stock
  , Case When SUM(isnull(a.Qty,0 ) -  isnull(b.QtyReceive,0)) IS NULL 
          then 0 
          else SUM(isnull(a.Qty,0 ) -  isnull(b.QtyReceive,0)) end  as RemainingStock
from  Products c 
left join InvoiceDetails  a on c.ProductID  = a.ProductID
left join PurchaseOrderDetails b on c.ProductID = b.ProductID  
Group By b.ProductID,c.ProductName