是否可以避免这种查询的子查询?

时间:2016-03-06 17:33:50

标签: sql sql-server sql-server-2008 grouping aggregate-functions

假设我有一张包含此类数据的表格:

Parent  Value           DateFor       ValueType
3177    50.110000       2016-03-05    1
3177    254390.000000   2016-03-05    2
3177    50.110000       2016-03-06    1
3177    254390.000000   2016-03-06    2
3294    40.800000       2016-03-05    1
3294    20280.000000    2016-03-05    2

Parent列的帮助下,我的表在Id上有一个PRIMARY索引(此处未显示id)和一个与父表的FOREIGN关系。

我想为每个Parent选择值类型的最新值:

3177    50.110000       2016-03-06    1
3177    254390.000000   2016-03-06    2
3294    40.800000       2016-03-05    1
3294    20280.000000    2016-03-05    2

解释:我忽略了2015-03-05对于父3177的两个值,因为它有2016-03-06的数据。但我从2016-03-05获取父母3294的数据,因为这是我最新的数据。

实现此目的的性能最高的查询是什么?因为我的桌子有数百万行...

是否可以避免子查询?

3 个答案:

答案 0 :(得分:3)

使用分析函数和覆盖索引可以在牺牲一些磁盘空间的情况下获得良好的性能;

CREATE INDEX ix_test 
       ON myTable([Parent], [ValueType], [DateFor] DESC) INCLUDE ([Value]);

GO

SELECT [Parent], [Value], [DateFor], [ValueType]
FROM (
  SELECT *, ROW_NUMBER() 
            OVER (PARTITION BY [Parent], [ValueType] ORDER BY [DateFor] DESC) rn
  FROM myTable
) z
WHERE rn=1;

答案 1 :(得分:1)

这个问题过于宽泛,因此答案是通用的。使用带有子查询的SQL查询或临时表(后者可能会带来更好的性能)。首先,按SELECT MAX(DateFor) as MinDate FROM [YourTable] Group BY [Parent], [ValueType]获取最早的日期(最小值),然后在SELECT子句中使用MinDate运行第二个WHERE语句。希望这会有所帮助。

答案 2 :(得分:1)

另一种可能具有良好性能的方法是:

SELECT [Parent], [Value], [DateFor], [ValueType]
FROM t
WHERE DateFor = (SELECT MAX(t2.DateFor)
                 FROM t t2
                 WHERE t2.Parent = t.Parent AND t2.ValueType = t.ValueType
                );

这需要与Joachim建议的索引相同的索引。在某些情况下,这可能会略微加快。您可以在数据上测试这两个。