SQL查询任务,决定?

时间:2010-04-01 08:18:04

标签: sql sql-server-2005 tsql optimization

MS SQL Server 2005中有一个货币汇率表:

ID | CURR |率| DATE
1 | USD | 30 | 01.10.2010
3 | GBP | 45 | 2010年7月10日
5 | USD | 31 | 2010年8月10日
7 | GBP | 46 | 2010年9月10日
9 | USD | 32 | 2010.12.10
11 | GBP | 48 |二○一○年三月一十日

费率实时更新,表格中有超过10亿行。

它需要编写一个SQL查询,它将提供每种货币的最新费率。 我的决定是:

SELECT c.[id],c.[curr],c.[rate],c.[date]    
FROM [curr_rate] c, (SELECT curr, MAX(date) AS rate_date FROM [curr_rate] 
      GROUP BY curr) t
WHERE c.date = t.rate_date AND c.curr = t.curr
ORDER BY c.[curr] ASC

是否可以编写没有子查询的查询并使用派生表连接?

4 个答案:

答案 0 :(得分:1)

不,我想不是。你有CURR索引和日期吗?

答案 1 :(得分:1)

在调优此查询时,排序索引可能比SQL语法更重要。

将子查询方法与CTE进行比较可能是值得的:

;WITH currCTE
AS
(
        SELECT id
               ,curr
               ,rate
               ,date
               ,ROW_NUMBER() OVER (PARTITION BY curr
                                   ORDER BY date desc
                                  ) AS rn
        FROM [curr_rate]
)
SELECT id
       ,curr
       ,rate
       ,date
FROM currCTE
WHERE rn = 1

如果表PK在id上,并且行总是按日期顺序添加到表中,则可以通过在排名的id子句中使用ORDER BY来获得更好的性能功能而非日期。

答案 2 :(得分:1)

您的查询不使用子查询,因此无需更改。子查询是一个SELECT查询,它返回单个值并嵌套在SELECT,INSERT,UPDATE或DELETE语句中,或嵌套在另一个子查询中。子查询可以在允许表达式的任何地方使用。见Subquery Fundamentals

您的查询使用的是派生表,也称为内联视图,您将其命名为“t”。

我首先要摆脱古老的连接语法:

SELECT 
    c.[id],c.[curr],c.[rate],c.[date]    
    FROM [curr_rate] c
        INNER JOIN (SELECT
                        curr, MAX(date) AS rate_date
                        FROM [curr_rate] 
                        GROUP BY curr
                   ) t ON c.curr = t.curr AND c.date = t.rate_date 
    ORDER BY c.[curr] ASC

但它将具有相同的执行计划。您可以将派生表移动到CTE中,但这与派生表大致相同。

如果您在以下位置创建索引视图,查询可能会运行得更快:

SELECT
    curr, MAX(date) AS rate_date
    FROM [curr_rate] 
    GROUP BY curr

带有curr + MAX(日期)的索引。如果你在[curr_rate] .curr + date上有一个索引,你的查询会有更好的表现并且是:

SELECT 
    c.[id],c.[curr],c.[rate],c.[date]    
    FROM [curr_rate] c
        INNER JOIN [curr_rate_max_view] t ON c.curr = t.curr AND c.date = t.rate_date 
    ORDER BY c.[curr] ASC

答案 3 :(得分:0)

我不知道你可以避免使用子选择,但你可以避免加入甚至是group by

SELECT id, curr, rate, date
FROM curr_rate r
WHERE date = (
       SELECT MAX(date)
         FROM curr_rate
        WHERE curr = r.curr
      )
ORDER BY curr ASC

我不知道这将如何表现。