当使用带有窗口聚合函数的 RANGE 选项时,我在 SQL Server 2012 中遇到了一些有趣的行为,并且不确定这是 SQL Server 2012 的错误还是“功能”。我有一个定义如下的表:
CREATE TABLE [Test].[Trades](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Member] [varchar](20) NOT NULL,
[TradeDate] [date] NOT NULL,
[Fund] [varchar](4) NOT NULL,
[Units] [decimal](28, 8) NOT NULL,
PRIMARY KEY CLUSTERED
(
[ID] ASC
)
);
此表存储成员在特定交易日期在基金中进行的交易。会员可以在给定日期对给定基金进行 >1 次交易。除了聚集索引之外,我还有一个非聚集索引,定义如下:
CREATE NONCLUSTERED INDEX [Ix_TradesIndex] ON [Test].[Trades]
(
[Member] ASC,
[Fund] ASC,
[TradeDate] ASC
)
INCLUDE ([Units]);
如果我想查询数据集以提供每个成员在每个基金中的运行总单位数,那么使用 SQL Server 2012 中窗口聚合的扩展,我可以回答如下问题:
SELECT T.Member, T.Fund, T.TradeDate,
SUM(T.Units) OVER(PARTITION BY T.Member, T.Fund
ORDER BY T.TradeDate
RANGE BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW) AS TotalShares
FROM Test.Trades AS T;
这将给我一个类似于下面的数据集(示例显示在 2005-02-03 在 Fund2 进行 >1 交易的成员):
……
Member1, Fund1, 2005-03-31, 0.00
会员1,基金2,2005-02-03,3256.50
会员1,基金2,2005-02-03,3256.50
……
RANGE 选项确保在排序条款不是唯一的(即,给定成员在特定交易日期对给定基金进行了多次交易)的情况下,窗口包括范围顶部的所有重复行。这按预期正常工作。但是,如果我想说“现在只给我这个集合中不同的行”(即去掉重复的条目),提出这个问题的一种方法如下:
SELECT DISTINCT T.Member, T.Fund, T.TradeDate, T.TotalShares
FROM
(
SELECT T.Member, T.Fund, T.TradeDate,
SUM(T.Units) OVER(PARTITION BY T.Member, T.Fund
ORDER BY T.TradeDate
RANGE BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW) AS TotalShares
FROM Test.Trades AS T
) AS T;
这里的事情变得有趣:我看到的是,如果计划并行,那么结果集是不确定的(即查询给出错误的答案,查询返回的行数可以在后续运行中改变)查询)。 如果计划不并行(我显然可以通过指定 OPTION(MAXDOP 1) 来强制执行),那么查询总是返回相同数量的行,如果结果集“正确”,则返回结果集。对我来说,这感觉就像 SQL Server 2012 中的一个错误。
我的问题是'<strong>是否有人对此行为有其他解释,或者这是一个错误?'</p>