Question

I want to avoid repeatedly using subqueries. My query is as follows:

;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. Please note the I am querying balQty and CurPrice twice each. Will that affect the efficiency and how to avoid it?

    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. how to use variable inside CTE? Thank you.

Was it helpful?

Solution

You can use Cross Apply to avoid repetition of balQty logic. You can use left join with Stock to get the cur price.

Using Variable inside CTE is same as you do it in regular query. Added a new variable @buysell to demonstrate that.

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

Method 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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top