提高子查询的性能
Improve Performance of Subquery
目前我有一个子查询,它本身有一个子查询。就性能而言,当我将其放入我的存储过程时,这不会很好。我想知道是否有任何方法可以提高这段代码的性能,或者看看不同的写法?
基本上我是在查找价格数据,但如果价格发生变化,我们只会将价格记录加载到我们的仓库中。所以我需要查找我们收到价格的每个工具的最新日期,然后 return 该价格。我有以下代码:
DECLARE @EndDate DATETIME
SET @EndDate = '2015-10-31'
SELECT
ip2.INSTR_ID
, ip2.PRC_TMS
, ip2.PRC_CURR_CDE
, COALESCE(MAX(CASE
WHEN ip2.PRC_TYP = 'CLO' THEN ip2.PRC_QUOTE_AMT
END),
MAX(ip2.PRC_QUOTE_AMT)) AS PRC_QUOTE_AMT
FROM ISSUE_PRICE AS ip2
INNER JOIN (
SELECT
INSTR_ID AS INSTR_ID
, MAX(PRC_TMS) AS PRC_TMS
FROM ISSUE_PRICE
WHERE PRC_SRCE_TYP = 'SSC'
AND PRC_TMS <= @EndDate
AND PRC_TYP IN ('LST', 'CLO')
GROUP BY INSTR_ID) AS i2
ON i2.INSTR_ID = ip2.INSTR_ID
AND i2.PRC_TMS = ip2.PRC_TMS
WHERE ip2.PRC_SRCE_TYP = 'SSC'
AND ip2.PRC_TYP IN ('LST', 'CLO')
GROUP BY ip2.PRC_TMS, ip2.INSTR_ID, ip2.PRC_CURR_CDE
任何帮助将不胜感激。
谢谢
这可以通过使用 Row_Number
window 函数来识别每个 INSTR_ID
的最大值 PRC_TMS
来实现。试试这个,
;WITH cte
AS (SELECT Row_number()OVER(partition BY INSTR_ID
ORDER BY PRC_TMS DESC) AS rn,*
FROM ISSUE_PRICE
WHERE PRC_SRCE_TYP = 'SSC'
AND PRC_TMS <= @EndDate
AND PRC_TYP IN ( 'LST', 'CLO' ))
SELECT ip2.INSTR_ID,
ip2.PRC_TMS,
ip2.PRC_CURR_CDE,
COALESCE(Max(CASE
WHEN ip2.PRC_TYP = 'CLO' THEN ip2.PRC_QUOTE_AMT
END), Max(ip2.PRC_QUOTE_AMT)) AS PRC_QUOTE_AMT
FROM cte
WHERE RN = 1
GROUP BY ip2.PRC_TMS,
ip2.INSTR_ID,
ip2.PRC_CURR_CDE
子查询不一定会导致性能问题。但是,您可以使用 window 函数更高效、更简洁地完成您想要的操作:
SELECT ip.INSTR_ID, ip.PRC_TMS, ip.PRC_CURR_CDE,
COALESCE(MAX(CASE WHEN ip.PRC_TYP = 'CLO' THEN ip.PRC_QUOTE_AMT
END),
MAX(ip.PRC_QUOTE_AMT)
) AS PRC_QUOTE_AMT
FROM (SELECT ip.*,
MAX(PRC_TMC) OVER (PARTITION BY INSTR_ID) as MAX_PRC_TMS
FROM ISSUE_PRICE ip
WHERE ip.PRC_SRCE_TYP = 'SSC' AND ip.PRC_TYP IN ('LST', 'CLO')
) ip
WHERE ip.PRC_TMS = ip.MAX_PRC_TMS
GROUP BY ip.PRC_TMS, ip.INSTR_ID, ip.PRC_CURR_CDE;
目前我有一个子查询,它本身有一个子查询。就性能而言,当我将其放入我的存储过程时,这不会很好。我想知道是否有任何方法可以提高这段代码的性能,或者看看不同的写法?
基本上我是在查找价格数据,但如果价格发生变化,我们只会将价格记录加载到我们的仓库中。所以我需要查找我们收到价格的每个工具的最新日期,然后 return 该价格。我有以下代码:
DECLARE @EndDate DATETIME
SET @EndDate = '2015-10-31'
SELECT
ip2.INSTR_ID
, ip2.PRC_TMS
, ip2.PRC_CURR_CDE
, COALESCE(MAX(CASE
WHEN ip2.PRC_TYP = 'CLO' THEN ip2.PRC_QUOTE_AMT
END),
MAX(ip2.PRC_QUOTE_AMT)) AS PRC_QUOTE_AMT
FROM ISSUE_PRICE AS ip2
INNER JOIN (
SELECT
INSTR_ID AS INSTR_ID
, MAX(PRC_TMS) AS PRC_TMS
FROM ISSUE_PRICE
WHERE PRC_SRCE_TYP = 'SSC'
AND PRC_TMS <= @EndDate
AND PRC_TYP IN ('LST', 'CLO')
GROUP BY INSTR_ID) AS i2
ON i2.INSTR_ID = ip2.INSTR_ID
AND i2.PRC_TMS = ip2.PRC_TMS
WHERE ip2.PRC_SRCE_TYP = 'SSC'
AND ip2.PRC_TYP IN ('LST', 'CLO')
GROUP BY ip2.PRC_TMS, ip2.INSTR_ID, ip2.PRC_CURR_CDE
任何帮助将不胜感激。
谢谢
这可以通过使用 Row_Number
window 函数来识别每个 INSTR_ID
的最大值 PRC_TMS
来实现。试试这个,
;WITH cte
AS (SELECT Row_number()OVER(partition BY INSTR_ID
ORDER BY PRC_TMS DESC) AS rn,*
FROM ISSUE_PRICE
WHERE PRC_SRCE_TYP = 'SSC'
AND PRC_TMS <= @EndDate
AND PRC_TYP IN ( 'LST', 'CLO' ))
SELECT ip2.INSTR_ID,
ip2.PRC_TMS,
ip2.PRC_CURR_CDE,
COALESCE(Max(CASE
WHEN ip2.PRC_TYP = 'CLO' THEN ip2.PRC_QUOTE_AMT
END), Max(ip2.PRC_QUOTE_AMT)) AS PRC_QUOTE_AMT
FROM cte
WHERE RN = 1
GROUP BY ip2.PRC_TMS,
ip2.INSTR_ID,
ip2.PRC_CURR_CDE
子查询不一定会导致性能问题。但是,您可以使用 window 函数更高效、更简洁地完成您想要的操作:
SELECT ip.INSTR_ID, ip.PRC_TMS, ip.PRC_CURR_CDE,
COALESCE(MAX(CASE WHEN ip.PRC_TYP = 'CLO' THEN ip.PRC_QUOTE_AMT
END),
MAX(ip.PRC_QUOTE_AMT)
) AS PRC_QUOTE_AMT
FROM (SELECT ip.*,
MAX(PRC_TMC) OVER (PARTITION BY INSTR_ID) as MAX_PRC_TMS
FROM ISSUE_PRICE ip
WHERE ip.PRC_SRCE_TYP = 'SSC' AND ip.PRC_TYP IN ('LST', 'CLO')
) ip
WHERE ip.PRC_TMS = ip.MAX_PRC_TMS
GROUP BY ip.PRC_TMS, ip.INSTR_ID, ip.PRC_CURR_CDE;