如何避免重复子查询

时间:2014-05-01 03:12:23

标签: sql-server subquery

我想避免重复使用子查询。我的查询如下:

;WITH Temp(Ticker, FromDate, ToDate, BuyingQty, SellingQty, ABP, ASP)
AS
(
select 
Ticker,
min(trxdate) as FromDate,
max(TrxDate) as ToDate,
case buysell when 'b' then SUM(Lot) end as BuyingQty,
case buysell when 's' then SUM(Lot) end as SellingQty,
case buysell when 'b' then CAST(SUM(Lot * price)/SUM(Lot) AS Decimal(10,2)) end as ABP,
case buysell when 's' then cast(SUM(Lot * price)/SUM(Lot) AS Decimal(10,2)) end as ASP
from transaksi where SettleDate is null
group by Ticker, buysell
)
select Ticker, 
Min(FromDate) as FromDate, 
Min(ToDate) as ToDate,
DATEDIFF(day, min(FromDate), max(ToDate)) as Days, 
SUM(buyingQty) as BuyingQty, 
SUM(sellingQty) as SellingQty,
case when(sum(sellingQty) is null) then SUM(BuyingQty) else SUM(buyingQty) - SUM(sellingQty) end as BalQty,
SUM(ABP) as ABP,
SUM(ASP) as ASP,
(SUM(ASP) - SUM(ABP)) * SUM(SellingQtY) AS Profit,
cast((SUM(ASP) - SUM(ABP)) / sum(ABP) * 100 as decimal(10,2))  AS [Profit%],
(select curprice from Stock where Temp.Ticker = Stock.Ticker) AS [Cur Price],
(select curprice from Stock where Temp.Ticker = Stock.Ticker) * 
case when(sum(sellingQty) is null) then SUM(BuyingQty) else (SUM(buyingQty) - SUM(sellingQty)) end as [Cur. Value]
from Temp group by Ticker order by 1,2
  1. 请注意,我每次查询balQtyCurPrice两次。这会影响效率以及如何避免它?

    balQty:

      case when(sum(sellingQty) is null) 
             then SUM(BuyingQty) 
             else SUM(buyingQty) - SUM(sellingQty) 
      end
    

    curprice:

    select curprice 
    from Stock 
    where Temp.Ticker = Stock.Ticker
    
  2. 如何在CTE中使用变量?谢谢。

1 个答案:

答案 0 :(得分:0)

您可以使用Cross Apply来避免重复balQty逻辑。您可以left joinStock一起使用cur price

在CTE中使用Variable与在常规查询中使用相同。添加了一个新变量@buysell来演示。

Declare @buySell varchar(1)
SET @buySell = 'a'


;WITH Temp(Ticker, FromDate, ToDate, BuyingQty, SellingQty, ABP, ASP)
AS
(
select 
Ticker,
min(trxdate) as FromDate,
max(TrxDate) as ToDate,
case buysell when 'b' then SUM(Lot) end as BuyingQty,
case buysell when 's' then SUM(Lot) end as SellingQty,
case buysell when 'b' then CAST(SUM(Lot * price)/SUM(Lot) AS Decimal(10,2)) end as ABP,
case buysell when 's' then cast(SUM(Lot * price)/SUM(Lot) AS Decimal(10,2)) end as ASP
from transaksi where SettleDate is null
and buysell = @buysell
  group by Ticker, buysell
)
select T.Ticker, 
Min(FromDate) as FromDate, 
Min(ToDate) as ToDate,
DATEDIFF(day, min(FromDate), max(ToDate)) as Days, 
SUM(buyingQty) as BuyingQty, 
SUM(sellingQty) as SellingQty,
SUM(C1.BalQty) AS BalQty,
SUM(ABP) as ABP,
SUM(ASP) as ASP,
(SUM(ASP) - SUM(ABP)) * SUM(SellingQtY) AS Profit,
cast((SUM(ASP) - SUM(ABP)) / sum(ABP) * 100 as decimal(10,2))  AS [Profit%],
SUM(S.curprice) AS [Cur Price],
SUM(S.curprice * C1.BalQty) as [Cur. Value]
from Temp T
LEFT JOIN Stock S ON T.Ticker = S.Ticker
CROSS APPLY (
SELECT  case when(T.sellingQty is null) then T.BuyingQty else T.buyingQty - T.sellingQty end AS BalQty
) C1


group by T.Ticker order by 1,2

方法2

;WITH Temp(Ticker, FromDate, ToDate, BuyingQty, SellingQty, ABP, ASP)
AS
(
select 
Ticker,
min(trxdate) as FromDate,
max(TrxDate) as ToDate,
case buysell when 'b' then SUM(Lot) end as BuyingQty,
case buysell when 's' then SUM(Lot) end as SellingQty,
case buysell when 'b' then CAST(SUM(Lot * price)/SUM(Lot) AS Decimal(10,2)) end as ABP,
case buysell when 's' then cast(SUM(Lot * price)/SUM(Lot) AS Decimal(10,2)) end as ASP
from transaksi where SettleDate is null
  group by Ticker, buysell
)
,CTE2 AS
(
select T.Ticker, 
Min(FromDate) as FromDate, 
Min(ToDate) as ToDate,
DATEDIFF(day, min(FromDate), max(ToDate)) as Days, 
SUM(buyingQty) as BuyingQty, 
SUM(sellingQty) as SellingQty,
SUM(ABP) as ABP,
SUM(ASP) as ASP,
(SUM(ASP) - SUM(ABP)) * SUM(SellingQtY) AS Profit,
cast((SUM(ASP) - SUM(ABP)) / sum(ABP) * 100 as decimal(10,2))  AS [Profit%],
S.curprice AS [Cur Price],
from Temp T
LEFT JOIN Stock S ON T.Ticker = S.Ticker
group by T.Ticker order by 1,2
)

SELECT
Ticker, 
FromDate, 
ToDate,
Days, 
BuyingQty, 
SellingQty,
C1.BalQty,
ABP,
ASP,
Profit,
[Profit%],
[Cur Price],
[Cur Price]*C1.BalQty AS [Cur Val]
FROM CTE2 T
CROSS APPLY (
SELECT  case when(T.sellingQty is null) then T.BuyingQty else T.buyingQty - T.sellingQty end AS BalQty
) C1