如何使此SQL更高效

时间:2018-11-22 00:08:09

标签: sql-server tsql relational-database

我已经编写了这段SQL,我知道有一些方法可以通过正确的实践使其运行得更快。

SELECT DISTINCT
    ACCOUNTNUM,
    FIRSTNAME AS NAME, 
    LASTNAME AS SURNAME, 
    (PHONE + ' ' + CELLULARPHONE) AS PHONENUM, 
    EMAIL,
    (SELECT TOP 1 CREATEDDATE 
     FROM RBOTRANSACTIONTABLE 
     WHERE CUSTACCOUNT = ACCOUNTNUM 
     ORDER BY CREATEDDATE DESC) AS LASTVISIT,  -- LAST VISIT, 
    (SELECT COUNT(TRANSACTIONID) 
     FROM RBOTRANSACTIONTABLE 
     WHERE CUSTACCOUNT = ACCOUNTNUM) AS TOTALVISITS, -- TOTAL VISITS, 
    (SELECT SUM(PAYMENTAMOUNT) 
     FROM RBOTRANSACTIONTABLE 
     WHERE CUSTACCOUNT = ACCOUNTNUM) AS TOTALSALES, -- TOTAL SALES,  
    (SELECT SUM(DISCAMOUNT) 
     FROM RBOTRANSACTIONTABLE 
     WHERE CUSTACCOUNT = ACCOUNTNUM) AS DISCOUNT
FROM 
    CUSTOMER 
LEFT OUTER JOIN 
    RBOTRANSACTIONTABLE ON CUSTACCOUNT = ACCOUNTNUM

我知道我是否在使用某种联接,我不必每次都要说FROM RBOTRANSACTIONTABLEEmail列之后的代码)。上面的代码可以很好地满足我的要求,但是我知道我的知识缺少缺失,我只是不知道什么

我正在寻找关于为什么不建议使用上述解决方案以及为什么要使用您的解决方案的深入答案。

2 个答案:

答案 0 :(得分:3)

您可以将查询重写为查找聚合的子查询的联接:

SELECT
    c.ACCOUNTNUM,
    c.FIRSTNAME AS NAME,
    c.LASTNAME AS SURNAME,
    (c.PHONE + ' ' + c.CELLULARPHONE) AS PHONENUM,
    c.EMAIL,
    a.LASTVISIT,
    COALESCE(a.TOTALVISITS, 0) AS TOTALVISITS,
    COALESCE(a.TOTALSALES, 0) AS TOTALSALES,
    COALESCE(a.DISCOUNT, 0) AS DISCOUNT
FROM CUSTOMER c
LEFT JOIN
(
    SELECT
        CUSTACCOUNT,
        MAX(CREATEDDATE) AS LASTVISIT,
        COUNT(TRANSACTIONID) AS TOTALVISITS,
        SUM(PAYMENTAMOUNT) AS TOTALSALES,
        SUM(DISCAMOUNT) AS DISCOUNT
    FROM RBOTRANSACTIONTABLE
    GROUP BY CUSTACCOUNT
) a
    ON c.ACCOUNTNUM = a.CUSTACCOUNT;

在引用SELECT子句中的列时,应该始终使用适当的别名。

答案 1 :(得分:1)

Tim绝对是重写查询的好方法。但是您也可以通过消除count(distinct)和外部联接来提高版本的效率:

SELECT ACCOUNTNUM,
       FIRSTNAME AS NAME, 
       LASTNAME AS SURNAME, 
       (PHONE + ' ' + CELLULARPHONE) AS PHONENUM, 
       EMAIL,
       (SELECT TOP 1 CREATEDDATE FROM RBOTRANSACTIONTABLE WHERE CUSTACCOUNT = ACCOUNTNUM ORDER BY CREATEDDATE DESC) AS LASTVISIT,  -- LAST VISIT, 
       (SELECT COUNT(TRANSACTIONID) FROM RBOTRANSACTIONTABLE WHERE CUSTACCOUNT = ACCOUNTNUM) AS TOTALVISITS, -- TOTAL VISITS, 
       (SELECT SUM(PAYMENTAMOUNT) FROM RBOTRANSACTIONTABLE WHERE CUSTACCOUNT = ACCOUNTNUM) AS TOTALSALES, -- TOTAL SALES,  
       (SELECT SUM(DISCAMOUNT) FROM RBOTRANSACTIONTABLE WHERE CUSTACCOUNT = ACCOUNTNUM) AS DISCOUNT
FROM CUSTOMER c;

有了正确的索引,它甚至可以比group by / join版本更好的性能。