CTE中查询的计算字段非常慢,如何优化

时间:2015-08-05 16:00:47

标签: sql sql-server-2005 common-table-expression

我有一个计算字段的查询,其中涉及在CTE中为每个字段查找数据集,但是当我到达其中几个字段时,它很慢。

这是一个想法:

;WITH TRNCTE AS
(
    SELECT TRN.PORT_N, TRN.TRADE_DATE, TRN.TRANS_TYPE, TRN.TRANS_SUB_CODE, TRN.SEC_TYPE, TRN.SETTLE_DATE 
    FROM TRNS_RPT TRN
    WHERE TRN.TRADEDT >= '2014-01-01' AND TRN.TRADEDT <= '2014-12-31'    
)

SELECT
    C.CLIENT_NAME,
    C.PORT_N,
    C.PHONE_NUMBER,
    CASE
        WHEN EXISTS(SELECT TOP 1 1 FROM TRNCTE WHERE PORT_N = C.PORT_N AND MONTH(SETTLE_DATE) = 12) THEN 'DECEMBER TRANSACTION'
        ELSE 'NOT DECEMBER TRANSACTION'
    END AS ALIAS1
FROM CLIENTS C
WHERE EXISTS(SELECT TOP 1 1 FROM TRNCTE WHERE PORT_N = C.PORT_N)

如果我有许多这些计算字段,查询最多可能需要10分钟才能执行。收集CTE中的数据大约需要15秒,大约有1,000,000条记录。

我真的不需要JOINS,因为我实际上并没有使用JOIN会做的数据,我只想检查TRNS_RPT中是否存在具有某些标准的记录,并将别名字段设置为某些值,无论我是否找到这样的记录与否。

你能帮我优化一下吗?感谢

2 个答案:

答案 0 :(得分:0)

在这种情况下你可以做些什么。您需要将cte的结果插入临时表中。这样您将节省重新计算的成本。 请试一试。

;WITH TRNCTE AS
    (
        SELECT TRN.PORT_N, TRN.TRADE_DATE, TRN.TRANS_TYPE, TRN.TRANS_SUB_CODE, TRN.SEC_TYPE, TRN.SETTLE_DATE 
        FROM TRNS_RPT TRN
        WHERE TRN.TRADEDT >= '2014-01-01' AND TRN.TRADEDT <= '2014-12-31'    
    )
SELECT * INTO #temp
FROM TRNCTE

    SELECT
        C.CLIENT_NAME,
        C.PORT_N,
        C.PHONE_NUMBER,
        CASE
        WHEN EXISTS(SELECT TOP 1 1 FROM #temp WHERE PORT_N = C.PORT_N AND MONTH(SETTLE_DATE) = 12) THEN 'DECEMBER TRANSACTION'
        ELSE 'NOT DECEMBER TRANSACTION'
    END AS ALIAS1
    FROM CLIENTS C
    WHERE EXISTS(SELECT TOP 1 1 FROM #temp WHERE PORT_N = C.PORT_N)

DROP TABLE #temp

答案 1 :(得分:0)

从查看代码开始,我可能会执行join,以避免在查询中包含TRNCTE两次。如果TRNCTE.PORT_N不唯一并且您将获得重复的行,则不完全相同。

;WITH TRNCTE AS
(
    SELECT TRN.PORT_N, TRN.TRADE_DATE, TRN.TRANS_TYPE, TRN.TRANS_SUB_CODE, TRN.SEC_TYPE, TRN.SETTLE_DATE 
    FROM TRNS_RPT TRN
    WHERE TRN.TRADEDT >= '2014-01-01' AND TRN.TRADEDT <= '2014-12-31'    
)
SELECT
    C.CLIENT_NAME,
    C.PORT_N,
    C.PHONE_NUMBER,
    CASE
        WHEN MONTH(TRNCTE.SETTLE_DATE) = 12) 
        THEN 'DECEMBER TRANSACTION'
        ELSE 'NOT DECEMBER TRANSACTION'
    END AS ALIAS1
FROM CLIENTS C
JOIN TRNCTE ON C.PORT_N = TRNCTE.PORT_N