【问题标题】:Subquery with multiple colums using count and sum and top使用 count 和 sum 和 top 具有多列的子查询
【发布时间】:2018-11-15 08:45:43
【问题描述】:

创建以下临时表:

  CREATE TABLE #BEDRAGEN(Dossiercode T_Code_Dossier,Detailcode T_Code_Detail,DetailSubcode T_Code_DetailSub
                        ,Totaalbedrag T_Fin_Amount,TotGefactDiensten T_Fin_Amount, TotGefactgoederen T_Fin_Amount, Verzonden int
                        ,TotaalInkord T_Fin_Amount, TotaalInkRgls int,Inkooporder T_Nr_Ord, InkOrdRgl T_LineNR)

  INSERT INTO #BEDRAGEN
  SELECT DD.DossierCode as Dossiercode,
         DD.DetailCode as Detailcode,
         DD.DetailSubCode as DetailSubcode,
         ISNULL(DBO.SIF_get_SalesAmountDosDetail(DD.Dossiercode,DD.Detailcode,DD.Detailsubcode),0) as Totaalbedrag,
         ISNULL((SELECT SUM(ID.InvDetailAmount)
                FROM T_InvoiceDetailDosDet as IDD
                inner join T_InvoiceDetail as ID on ID.InvCode=IDD.InvCode and ID.InvLineNr=IDD.InvLinenr
                WHERE IDD.DossierCode=DD.Dossiercode AND IDD.DetailCode=DD.Detailcode AND IDD.DetailSubCode=DD.DetailSubcode),0) 
                AS TotGefactDiensten,
         ISNULL((SELECT SUM(ID.InvDetailAmount)
                from T_InvoiceDetailShipDet as InvSD
                inner join T_ShippingDetail as SD on SD.ShipDocCode=InvSD.ShipDocCode and SD.ShipLineNr=InvSD.ShipLineNr
                inner join T_InvoiceDetail as ID on ID.InvCode=InvSD.InvCode and ID.InvLineNr=InvSD.InvLinenr
                where SD.DossierCode=DD.Dossiercode AND SD.DetailCode=DD.Detailcode AND SD.DetailSubCode=DD.DetailSubcode),0) as TotGefactgoederen,
         ISNULL((select sum(Verz.DelQty) 
                from dbo.T_DeliveryLine as Verz
                where Verz.DossierCode=DD.Dossiercode and Verz.DetailCode=DD.Detailcode and Verz.DetailSubCode=DD.DetailSubcode),0) as Verzonden,
         ISNULL((select sum(PDPL.BasicCurrTotalAmount) 
                from T_PurDocPartLineDosDetLink AS PDL
                INNER JOIN T_PurchaseDocument as PD on PDL.PurDocCode=PD.PurDocCode
                INNER JOIN T_PurDocPartLine as PDPL on PDPL.PurDocCode=PDL.PurDocCode and PDPL.PDPartLineNr=PDL.PDPartLineNr
                WHERE PDL.DossierCode=DD.DossierCode AND PDL.DetailCode=DD.DetailCode AND PDL.DetailSubCode=DD.DetailSubCode),0) AS TotaalInkord,
         ISNULL((select COUNT(PDL.DetailCode) 
                from T_PurDocPartLineDosDetLink AS PDL
                INNER JOIN T_PurchaseDocument as PD on PDL.PurDocCode=PD.PurDocCode
                INNER JOIN T_PurDocPartLine as PDPL on PDPL.PurDocCode=PDL.PurDocCode and PDPL.PDPartLineNr=PDL.PDPartLineNr
                WHERE PDL.DossierCode=DD.DossierCode AND PDL.DetailCode=DD.DetailCode AND PDL.DetailSubCode=DD.DetailSubCode),0) AS TotaalInkRgls,
         ISNULL((SELECT TOP 1 PD.PurOrdNr FROM T_PurDocPartLineDosDetLink AS PDL 
                INNER JOIN T_PurchaseDocument as PD on PDL.PurDocCode=PD.PurDocCode
                INNER JOIN T_PurDocPartLine AS INR ON INR.PurDocCode=PDL.PurDocCode AND INR.PDPartLineNr=PDL.PDPartLineNr
                WHERE  PDL.DossierCode=DD.Dossiercode AND PDL.DetailCode=DD.Detailcode AND PDL.DetailSubCode=DD.DetailSubCode),'') AS Inkooporder,
        ISNULL((SELECT TOP 1 PDL.PDPartLineNr FROM T_PurDocPartLineDosDetLink AS PDL 
                INNER JOIN T_PurchaseDocument as PD on PDL.PurDocCode=PD.PurDocCode
                INNER JOIN T_PurDocPartLine AS INR ON INR.PurDocCode=PDL.PurDocCode AND INR.PDPartLineNr=PDL.PDPartLineNr
                WHERE  PDL.DossierCode=DD.Dossiercode AND PDL.DetailCode=DD.Detailcode AND PDL.DetailSubCode=DD.DetailSubCode),0) AS InkOrdRgl
  FROM dbo.T_DossierDetail AS DD
  Inner Join    dbo.T_Part  AS P On P.PartCode = DD.PartCode
  Inner Join    dbo.T_DossierMain  AS DM On DM.DossierCode = DD.DossierCode
  Inner Join    dbo.T_DossierStatus  AS DS On DS.DossierStatusCode = DD.DossierStatusCode
  WHERE    DD.DossierCode > N''

 select * from #bedragen

 drop table #BEDRAGEN

如您所见,获取 TotaalInkord、TotaalInkRgls、Inkooporder、InkOrdRgl 列的子查询 使用相同的 from/innerjoin 和 where。

有没有可能将这些结合起来? 如果可以合并会更快吗?

谢谢

背景: 我需要这个临时表来加快存储过程的性能。 此存储过程是一个大型选择,使用许多函数来获取其列。 这个函数内容我现在已经添加到 temptable 中了。

【问题讨论】:

  • 您使用的是哪个 dbms? (该代码是特定于产品的。)
  • sql server.. 我猜..
  • 是的,它是 sql server
  • 2012 具体

标签: sql subquery temp-tables


【解决方案1】:

没有样本数据很难,但 CROSS APPLY 应该可以解决问题 - 不能说它是否会表现更好(但应该),您可能需要稍微调整一下。

CREATE TABLE #BEDRAGEN(Dossiercode T_Code_Dossier,Detailcode T_Code_Detail,DetailSubcode T_Code_DetailSub
                        ,Totaalbedrag T_Fin_Amount,TotGefactDiensten T_Fin_Amount, TotGefactgoederen T_Fin_Amount, Verzonden int
                        ,TotaalInkord T_Fin_Amount, TotaalInkRgls int,Inkooporder T_Nr_Ord, InkOrdRgl T_LineNR)

  INSERT INTO #BEDRAGEN
  SELECT DD.DossierCode as Dossiercode,
         DD.DetailCode as Detailcode,
         DD.DetailSubCode as DetailSubcode,
         ISNULL(DBO.SIF_get_SalesAmountDosDetail(DD.Dossiercode,DD.Detailcode,DD.Detailsubcode),0) as Totaalbedrag,
         sub.TotGefactDiensten,
         sub.TotGefactgoederen,
         sub.Verzonden,
         sub.TotaalInkord,
         sub.TotaalInkRgls,
         sub.Inkooporder,
         sub.InkOrdRgl
  FROM dbo.T_DossierDetail AS DD
  Inner Join    dbo.T_Part  AS P On P.PartCode = DD.PartCode
  Inner Join    dbo.T_DossierMain  AS DM On DM.DossierCode = DD.DossierCode
  Inner Join    dbo.T_DossierStatus  AS DS On DS.DossierStatusCode = DD.DossierStatusCode
  cross apply (
        SELECT 
            ISNULL(SUM(ID.InvDetailAmount), 0) as TotGefactDiensten
            ISNULL(SUM(ID.InvDetailAmount), 0) as as TotGefactgoederen
            ISNULL(sum(Verz.DelQty) ,0) as Verzonden,
            ISNULL(sum(PDPL.BasicCurrTotalAmount) ,0) AS TotaalInkord,
            ISNULL(COUNT(PDL.DetailCode) ,0) AS TotaalInkRgls,
            ISNULL(min(PD.PurOrdNr), '') AS Inkooporder,  -- assuming this PD.PurOrdNr is the same for all records of subquery ???
            ISNULL(min(PDL.PDPartLineNr),0) AS InkOrdRgl
        FROM T_PurDocPartLineDosDetLink AS PDL 
        INNER JOIN T_PurchaseDocument as PD on PDL.PurDocCode=PD.PurDocCode
        INNER JOIN T_PurDocPartLine AS INR ON INR.PurDocCode=PDL.PurDocCode AND INR.PDPartLineNr=PDL.PDPartLineNr
        WHERE  PDL.DossierCode=DD.Dossiercode AND PDL.DetailCode=DD.Detailcode AND PDL.DetailSubCode=DD.DetailSubCode
    ) sub

WHERE    DD.DossierCode > N''

 select * from #bedragen

 drop table #BEDRAGEN

【讨论】:

  • 谢谢。我尝试了outerapply(参见答案中的代码)与交叉应用有什么区别?
  • --假设这个 PD.PurOrdNr 对于子查询的所有记录都是一样的???它不需要。大多数时候它会。但也可以有2个或3个,只需要显示第一个即可。因此我的 TOP 1
  • 交叉应用通常更快。 APPLY 使右侧查询在左侧查询的每个结果中执行一次。 CROSS 只考虑匹配行,如 INNER JOIN。使用 OUTER 会考虑左侧查询中的所有行。但是,当聚合右侧的所有列时,交叉应用也像外连接一样 - 在不匹配时不会“松散”整行。
【解决方案2】:
INSERT INTO #BEDRAGEN
      SELECT DD.DossierCode as Dossiercode,
             DD.DetailCode as Detailcode,
             DD.DetailSubCode as DetailSubcode,
             ISNULL(DBO.SIF_get_SalesAmountDosDetail(DD.Dossiercode,DD.Detailcode,DD.Detailsubcode),0) as Totaalbedrag,
             ISNULL((SELECT SUM(ID.InvDetailAmount)
                    FROM T_InvoiceDetailDosDet as IDD
                    inner join T_InvoiceDetail as ID on ID.InvCode=IDD.InvCode and ID.InvLineNr=IDD.InvLinenr
                    WHERE IDD.DossierCode=DD.Dossiercode AND IDD.DetailCode=DD.Detailcode AND IDD.DetailSubCode=DD.DetailSubcode),0) 
                    AS TotGefactDiensten,
             ISNULL((SELECT SUM(ID.InvDetailAmount)
                    from T_InvoiceDetailShipDet as InvSD
                    inner join T_ShippingDetail as SD on SD.ShipDocCode=InvSD.ShipDocCode and SD.ShipLineNr=InvSD.ShipLineNr
                    inner join T_InvoiceDetail as ID on ID.InvCode=InvSD.InvCode and ID.InvLineNr=InvSD.InvLinenr
                    where SD.DossierCode=DD.Dossiercode AND SD.DetailCode=DD.Detailcode AND SD.DetailSubCode=DD.DetailSubcode),0) as TotGefactgoederen,
             ISNULL((select sum(Verz.DelQty) 
                    from dbo.T_DeliveryLine as Verz
                    where Verz.DossierCode=DD.Dossiercode and Verz.DetailCode=DD.Detailcode and Verz.DetailSubCode=DD.DetailSubcode),0) as Verzonden,
             ISNULL(IO.waarde,0) as TotaalInkord,
             ISNULL(IO.rgls,0) as TotaalInkRgls,
             ISNULL(IO.PurOrdNr,'') as Inkooporder,
             ISNULL(IO.PDPartLineNr,'') as InkOrdRgl
      FROM dbo.T_DossierDetail AS DD
      Inner Join    dbo.T_Part  AS P On P.PartCode = DD.PartCode
      Inner Join    dbo.T_DossierMain  AS DM On DM.DossierCode = DD.DossierCode
      Inner Join    dbo.T_DossierStatus  AS DS On DS.DossierStatusCode = DD.DossierStatusCode
      Inner Join    #StatusType ST on DS.DossierStatusType = ST.StatusType
      OUTER APPLY (SELECT top 1 PD.PurOrdNr,PDL.PDPartLineNr,COUNT(PDL.DetailCode) as rgls,sum(PDPL.BasicCurrTotalAmount) as waarde 
                    FROM T_PurDocPartLineDosDetLink AS PDL 
                    INNER JOIN T_PurchaseDocument as PD on PDL.PurDocCode=PD.PurDocCode
                    INNER JOIN T_PurDocPartLine AS PDPL ON PDPL.PurDocCode=PDL.PurDocCode AND PDPL.PDPartLineNr=PDL.PDPartLineNr
                    WHERE  PDL.DossierCode=DD.Dossiercode AND PDL.DetailCode=DD.Detailcode AND PDL.DetailSubCode=DD.DetailSubCode
                    GROUP BY PD.PurOrdNr,PDL.PDPartLineNr,PDL.DetailCode,PDPL.BasicCurrTotalAmount)  IO
      WHERE    DD.DossierCode > N''

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    相关资源
    最近更新 更多