Sql server 使用group by优化SQL Server连接查询

Sql server 使用group by优化SQL Server连接查询,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我只是想知道,下面给出的查询是否可以通过任何其他可行的方式实现,比如使用GROUPBY SELECT GROUPMAS.GRPCODE, GROUPMAS.GRPNAME, GRPDTLS.ACCODE, GRPDTLS.ACNAME, GRPDTLS.DOA "ADMISSION DATE", LOANMAST.LOANCODE, LOANMAST.VCHDATE "LOAN SANCTION DATE",

我只是想知道,下面给出的查询是否可以通过任何其他可行的方式实现,比如使用GROUPBY

        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')
表GRPDTLS结构

GRPCODE | GRPNAME
--------| -------
1       | A
2       | B
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
LOANCODE | GRPCODE | ACCODE | VCHDATE  | LANAMT
---------|---------|--------|--------- |--------
1        | 1       | 2      |2009-01-06|2000
2        | 2       | 1      |2008-09-06|5000
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
表LoanMaster结构

GRPCODE | GRPNAME
--------| -------
1       | A
2       | B
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
LOANCODE | GRPCODE | ACCODE | VCHDATE  | LANAMT
---------|---------|--------|--------- |--------
1        | 1       | 2      |2009-01-06|2000
2        | 2       | 1      |2008-09-06|5000
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
表RECPDTLS结构

GRPCODE | GRPNAME
--------| -------
1       | A
2       | B
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
LOANCODE | GRPCODE | ACCODE | VCHDATE  | LANAMT
---------|---------|--------|--------- |--------
1        | 1       | 2      |2009-01-06|2000
2        | 2       | 1      |2008-09-06|5000
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

感谢您的帮助。

您可以根据需要将select语句中的子查询替换为左外部联接或内部联接。如果所有LOANCODE记录都有匹配的RECPDTLS记录,则使用内部联接,否则使用左外部联接。保持聚合函数不变

 ...
 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,请确保使用LET-OUTER-JOIN,因为内部连接只会在两个表中返回匹配项。

您可以使用以下方法简化请求:

;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'

您可以添加当前查询的输出吗?一个建议是,您可以将三个子查询或还款、利息、上次付款放在一个查询中,并根据您需要的记录数进行联接或交叉应用。根据经验,如果您有多个子查询,都是从同一来源选择的,正如上面DVT所提到的,通常有一种方法可以合并它们。第二种方法工作得很好,速度也很快,但第一种方法产生了错误的列还款和利息结果,执行和返回5414行需要17秒,而所有其他查询都会在几毫秒内产生结果。无论如何,谢谢@ross bushI删除了第一个。它加入同一张桌子三次而不是一次。我意识到,在我看到每个聚合在联接表上都有相同的筛选器之后,所以您只需要一个联接。我感谢您的努力@ross bush,但我认为您应该再次编辑您的答案,as GROUP BY子句也是运行此查询所必需的。但是与RECPDTLS的左外部联接不会返回没有匹配RECPDTLS记录的LOANMAST的LOANCODE。那么,我们可以为这个问题做些什么呢?更新了答案,并添加了关于左外连接用法的注释。您也可以继续使用左外部联接,但是,在where子句中添加where NOT RECPDTLS.ID为NULL,这可能不是必需的。如果只需要匹配的记录,请使用和内部联接。