需要帮助优化sql查询

时间:2013-11-15 07:08:26

标签: sql sql-server

我有一个跟踪共同基金投资的网站。为此,我有下面的表结构(结构已被修改,以删除不需要的列,以便把注意力集中在我的问题上)

表#1:scheme_Mst

|Scheme_ID | fundHouse_Id | OpeningBalance | OpeningUnits
----------------------------------------------------------
|1         |  1           | 100            |  10 

表#2投资

|Scheme_ID | InvestedAmt   | InvestedUnits | statusFlag
----------------------------------------------------------
|1         | 50            |  5            | A

表#3兑换

|Scheme_ID | redemedAmt    | redemedUnits  | statusFlag
----------------------------------------------------------
|1         | 50            |  5            | A

表#4 SwitchDetails

|From_Scheme_ID |To_Scheme_ID |switchInAmt |switchInUnits |switchOutAmt |switchOutUnits | StaFlag
------------------------------------------------------------------------------------------
|1              | 2           | 20         | 2            | 10          | 1             | A

表#5 BonusDetails

|Scheme_ID | BonusAmt   | BonusUnits | statusFlag
----------------------------------------------------------
|1         | 50         |  5         | A

表#6 Divident_Detais

|Scheme_ID | DividentAmt | DividentUnits | statusFlag
----------------------------------------------------------
|1         | 50          |  5            | A

现在要了解我在下面查询的方案中可用单位的详细信息....(这是非常非常昂贵的)

SELECT *,
       CASE
           WHEN OutstandingUnits <> 0 THEN CONVERT(decimal(18,2),Outstanding/OutstandingUnits)
           ELSE 0
       END AS WAC
FROM
  (SELECT *,
          ISNULL(OpeningBalance,0) + ISNULL(DividendAmount,0) + ISNULL(bonusAmount,0) + ISNULL(invstAmount,0) + ISNULL(SwitchedInAmount,0) - ISNULL(redeemedAmount,0) - ISNULL(SwitchedOutAmount,0) AS Outstanding,
          ISNULL(openingUnits,0) + ISNULL(DividendUnits,0) + ISNULL(bonusUnits,0) + ISNULL(invstUnits,0) + SNULL(SwitchedInUnits,0) - ISNULL(redeemedUnits,0) - ISNULL(SwitchedOutUnits,0) AS OutstandingUnits
   FROM
     (SELECT C.scheme_ID,D.schemeName, D.Openingbalance AS OpeningBalance, D.OpeningUnits AS openingUnits, ISNULL(SUM(C.invstAmount),0) AS invstAmount, ISNULL(SUM(C.invstUnits),0) AS invstUnits,
        (SELECT ISNULL(SUM(redemedAmt),0)
         FROM redemption
         WHERE StatusFlag='A'
           AND scheme_ID = C.scheme_ID) AS redeemedAmount,
        (SELECT ISNULL(SUM(redeemedUnits),0)
         FROM redemption
         WHERE StatusFlag='A'
           AND scheme_ID = C.scheme_ID) AS redeemedUnits,
        (SELECT ISNULL(sum(switchOutAmt),0)
         FROM SwitchDetails
         WHERE BB.Status = 'A'
           AND BB.From_Scheme_Id = C.scheme_ID) AS SwitchedOutAmount,
        (SELECT ISNULL(sum(switchOutUnits),0)
         FROM SwitchDetails
         WHERE BB.Status = 'A'
           AND BB.From_Scheme_Id = C.scheme_ID) AS SwitchedOutUnits,
        (SELECT ISNULL(sum(switchOutAmt),0)
         FROM SwitchDetails
         WHERE BB.Status = 'A'
           AND BB.From_Scheme_Id = C.scheme_ID) AS SwitchedInAmount,
        (SELECT ISNULL(sum(SwitchedInUnits),0)
         FROM SwitchDetails
         WHERE BB.Status = 'A'
           AND BB.From_Scheme_Id = C.scheme_ID) AS SwitchedInUnits, .. same way
      FOR bonus
      AND divident ..
      FROM Investment c) tab)tab2

此查询应该产生以下输出..(样本输出)

Scheme_ID| Scheme_Name | OpeningBalance | OpeningUnits | InvstAmount | invstUnits | redemedAmount | redemedUnits | SwitchedOutAmt | SwitchOutUnit | bonusAmt | bonusUnit | DividentAmount | DividentUnit | Outstanding | OutstandingUnit | WAC
-------------------------------------------------------------------------------------------

这就是我计算细节的方式。请建议我更好的方法。

我正在使用sql server 2008

2 个答案:

答案 0 :(得分:0)

具有相同条件的子查询可能是这种情况下性能最差的敌人。

尝试使用此内部查询:

SELECT 
    c.scheme_ID,
    d.schemeName,
    d.Openingbalance AS OpeningBalance,
    d.OpeningUnits AS openingUnits,
    ISNULL(SUM(c.invstAmount), 0) AS invstAmount,
    ISNULL(SUM(c.invstUnits), 0) AS invstUnits,

    ISNULL(SUM(r.redemedAmt), 0) AS redeemedAmount,
    ISNULL(SUM(r.redeemedUnits), 0) AS redeemedUnits, 
    ISNULL(SUM(r.switchOutAmt), 0) AS SwitchedOutAmount,
    ISNULL(SUM(r.switchOutUnits), 0) AS SwitchedOutUnits,
    ISNULL(SUM(r.switchOutAmt), 0) AS SwitchedInAmount,
    ISNULL(SUM(r.SwitchedInUnits), 0) AS SwitchedInUnits
FROM Investment AS c
INNER JOIN redemption AS r 
    ON r.StatusFlag='A' AND r.scheme_ID = C.scheme_ID
--INNER JOIN someTable AS d...

答案 1 :(得分:0)

你可以做这样的事情(我没有插入GROUP BY子句或总结Openingbalance, OpeningUnits你更了解你的查询逻辑,我只是​​为了表现而编辑):

SELECT *,
       CASE
           WHEN OutstandingUnits <> 0 THEN CONVERT(decimal(18,2),Outstanding/OutstandingUnits)
           ELSE 0
       END AS WAC
FROM
     (SELECT C.scheme_ID,
             D.schemeName, 
             D.Openingbalance AS OpeningBalance, 
             D.OpeningUnits AS openingUnits, 
             ISNULL(SUM(C.invstAmount),0) AS invstAmount, 
             ISNULL(SUM(C.invstUnits),0) AS invstUnits,
         ISNULL(SUM(r.redemedAmt),0) redeemedAmount,
         ISNULL(SUM(r.redeemedUnits),0) redeemedUnits,
         ISNULL(sum(sd.switchOutAmt),0) SwitchedOutAmount,
         ISNULL(sum(sd.switchOutUnits),0) SwitchedOutUnits,
         ISNULL(sum(sd.switchOutAmt),0) SwitchedInAmount,
         ISNULL(sum(sd.SwitchedInUnits),0) SwitchedInUnits,
          --The sum columns from above query
          ISNULL(OpeningBalance,0) + ISNULL(DividendAmount,0) + ISNULL(bonusAmount,0) + ISNULL(invstAmount,0) + 
          ISNULL(SwitchedInAmount,0) - ISNULL(redeemedAmount,0) - ISNULL(SwitchedOutAmount,0) AS Outstanding,
          ISNULL(openingUnits,0) + ISNULL(DividendUnits,0) + ISNULL(bonusUnits,0) + ISNULL(invstUnits,0) + 
          ISNULL(SwitchedInUnits,0) - ISNULL(redeemedUnits,0) - ISNULL(SwitchedOutUnits,0) AS OutstandingUnits,
          ----
      .. same way
      FOR bonus
      AND divident ..
      FROM Investment c
      LEFT JOIN redemption r
       ON r.StatusFlag='A'
       AND r.scheme_ID = C.scheme_ID
      LEFT JOIN SwitchDetails sd
       ON sd.Status = 'A'
       AND sd.From_Scheme_Id = C.scheme_ID
       ) tab