2017-02-28 76 views
0

只是为了知识,我想知道,下面给出的查询可以通过任何其他可行的方式实现,如使用group by。SQL Server连接查询优化与组通过

 SELECT 
     GROUPMAS.GRPCODE, GROUPMAS.GRPNAME, 
     GRPDTLS.ACCODE, GRPDTLS.ACNAME, GRPDTLS.DOA "ADMISSION DATE", 
     LOANMAST.LOANCODE, LOANMAST.VCHDATE "LOAN SANCTION DATE", 
     LOANMAST.LANAMT, 
     (SELECT SUM(RECPDTLS.INSTAMT) 
      FROM RECPDTLS 
      WHERE LOANCODE = LOANMAST.LOANCODE 
      AND RECPDTLS.VCHDATE <= '2009-03-31') AS REPAYMENT, 
     (SELECT SUM(RECPDTLS.INTAMT) 
      FROM RECPDTLS 
      WHERE LOANCODE = LOANMAST.LOANCODE 
      AND RECPDTLS.VCHDATE <= '2009-03-31') AS INTREST, 
     (SELECT MAX(RECPDTLS.VCHDATE) 
      FROM RECPDTLS 
      WHERE LOANCODE = LOANMAST.LOANCODE 
      AND RECPDTLS.VCHDATE <= '2009-03-31') AS "LAST PAYMENT ON" 
    FROM 
     GROUPMAS 
    JOIN 
     GRPDTLS ON (GROUPMAS.GRPCODE = GRPDTLS.GRPCODE AND GRPDTLS.DOA <= '2009-03-31') 
    JOIN 
     LOANMAST ON (GRPDTLS.GRPCODE = LOANMAST.GRPCODE AND GRPDTLS.ACCODE = LOANMAST.ACCODE AND LOANMAST.VCHDATE <= '2009-03-31') 

表GROUPMAS结构

GRPCODE | GRPNAME 
--------| ------- 
1  | A 
2  | B 

表GRPDTLS结构

GRPCODE | ACCODE | ACNAME | DOA 
--------|--------|--------|----- 
1  | 1  | name1A | 2007-07-05 
1  | 2  | name2A | 2008-07-05 
2  | 1  | name1B | 2007-07-06 
2  | 2  | name2B | 2007-07-05 

表LOANMAST结构

LOANCODE | GRPCODE | ACCODE | VCHDATE | LANAMT 
---------|---------|--------|--------- |-------- 
1  | 1  | 2  |2009-01-06|2000 
2  | 2  | 1  |2008-09-06|5000 

表RECPDTLS结构

TXNNO | LOANCODE | INSTAMT | INTAMT | VCHDATE 
------|----------|---------|--------|--------- 
1  | 1  | 200  | 0  | 2009-02-06 
2  | 1  | 200  | 10  | 2009-03-06 
3  | 2  | 500  | 0  | 2008-10-06 
4  | 2  | 1500 | 50  | 2009-03-28 
5  | 2  | 500  | 0  | 2010-03-28 

它会输出这样的事情

GRPCODE | GRPNAME | ACCODE | ACNAME | ADMISSION DATE | LOANCODE | LOAN SANCTION DATE | LANAMT | REPAYMENT | INTREST | LAST PAYMENT ON 
--------| --------| -------| ------ | ---------------| -------- | ------------------ | -------| ----------| ------- | -------------- 
1  | A  | 2  | name2A | 2008-07-05  | 1  |2009-01-06   | 2000 | 400  | 10  | 2009-03-06 
2  | B  | 1  | name1B | 2007-07-06  | 2  |2008-09-06   | 5000 | 2000  | 50  | 2009-03-28 

感谢您的帮助。

+0

你可以添加当前查询的输出? – SqlZim

+0

一个建议是,您可以在一个查询中放入三个子查询或“REPAYMENT”,“INTEREST”,“LAST PAYMENT ON”,并根据您需要的记录数量进行JOIN(或CROSS APPLY)。 – DVT

+0

作为一个经验法则,如果您有多个子查询都从同一个源中进行选择,通常有一种方法可以将它们合并(如上面所述的DVT)。 – Santi

回答

0

根据需要,您可以用LEFT OUTERINNER JOIN替换select语句中的子查询。如果所有LOANCODE记录都具有匹配的RECPDTLS记录,则使用INNER JOIN,否则使用LEFT OUTER JOIN。保持你的聚合函数相同。

... 
Repayment=SUM(RECPDTLS.INSTAMT), 
Interest=SUM(RECPDTLS.INTAMT), 
LastPaymentOn=MAX(RECPDTLS.VCHDATE) 
... 
LEFT OUTER/INNER JOIN RECPDTLS ON RECPDTLS.LOANCODE = LOANMAST.LOANCODE AND Repayment.VCHDATE <= @HighDate 
... 
GROUP BY 
    GROUPMAS.GRPCODE, GROUPMAS.GRPNAME, 
    GRPDTLS.ACCODE, GRPDTLS.ACNAME, GRPDTLS.DOA, 
    LOANMAST.LOANCODE, LOANMAST.VCHDATE, 
    LOANMAST.LANAMT 

您将需要运行查询分析器来查看旧查询和新查询之间的效率增益。

注意:正如我上面所说,如果LOANCODE不需要有RECPDTLS作为INNER JOIN将只返回两个表中的匹配,请务必使用LET OUTER JOIN。

+0

第二个工作正常,速度也很快,但是第一个错误的结果是列** REPAYMENT **和** INTEREST **,它需要17秒来执行并返回5414行,其中所有其他查询都是在几毫秒内产生结果。任何方式谢谢@ ross-bush –

+0

我删除了第一个。它将3次加入同一张桌子,而不是一次。我意识到,在看到每个聚合在连接的表上有相同的过滤器后,您只需要一次连接。 –

+0

我感谢你的努力@罗斯布什,但我认为你应该再次编辑你的答案,因为** GROUP BY **子句也是运行此查询所必需的。 –

0

您可以使用CTE简化要求:

;WITH LOANMASTAGG AS 
(
    SELECT SUM(r.INSTAMT) REPAYMENT, SUM(r.INTAMT) INTREST, MAX(r.VCHDATE) [LAST PAYMENT ON], l.LOANCODE, l.VCHDATE, l.LANAMT, l.ACCODE, l.GRPCODE 
    FROM @RECPDTLS r 
     INNER JOIN @LOANMAST l ON r.LOANCODE = l.LOANCODE 
    WHERE l.VCHDATE <= '2009-03-31' 
    GROUP BY l.LOANCODE, l.VCHDATE, l.LANAMT, l.ACCODE, l.GRPCODE 
) 
SELECT 
     g.GRPCODE, 
     g.GRPNAME, 
     gl.ACCODE, 
     gl.ACNAME, 
     gl.DOA "ADMISSION DATE", 
     la.LOANCODE, 
     la.VCHDATE "LOAN SANCTION DATE", 
     la.LANAMT, 
     la.REPAYMENT AS REPAYMENT, 
     la.INTREST AS INTREST, 
     la.[LAST PAYMENT ON] "LAST PAYMENT ON" 
FROM LOANMASTAGG la 
     INNER JOIN @GRPDTLS gl ON gl.GRPCODE = la.GRPCODE AND gl.ACCODE = la.ACCODE 
     INNER JOIN @GROUPMAS g ON (g.GRPCODE = gl.GRPCODE) 
WHERE gl.DOA <= '2009-03-31'