首页 > 解决方案 > 时态表以一种奇怪的模式检索具有不同顺序的分区行集

问题描述

我正在解决一项基于 Adventure Works 2012 的任务。

对于每个财政年度(2007 年和 2008 年),找出累计运行收入总额达到 1000 万美元的第一个日期。

输出应包括以下列:

DROP TABLE #data
SELECT YEAR(DATEADD(MONTH, 6, OrderDate)) FiscalYear, CAST(OrderDate AS DATE) OrderDate, SalesOrderID OrderID,
COUNT(*)        OVER(Partition BY YEAR(DATEADD(MONTH, 6, OrderDate)) ORDER BY SalesOrderID) OrderCount,
SUM(SubTotal)   OVER(Partition BY YEAR(DATEADD(MONTH, 6, OrderDate)) ORDER BY SalesOrderID) RunTotal
INTO #data
FROM sales.SalesOrderHeader
WHERE YEAR(DATEADD(MONTH, 6, OrderDate)) IN (2007, 2008)

SELECT TOP 1 FiscalYear, OrderDate, OrderCount, OrderID, RunTotal
FROM #data
WHERE RunTotal>=10000000 AND FiscalYear=2007
UNION
SELECT TOP 1 FiscalYear, OrderDate, OrderCount, OrderID, RunTotal
FROM #data
WHERE RunTotal>=10000000 AND FiscalYear=2008

时态表 #data 检索按 FiscalYear 分区的正确集合,并按 OrderID 在分区内排序 3 次连续执行,并在以下 UNION 查询中呈现正确结果 在 此处输入图像描述

但是,在接下来的 2 次执行中,顺序被打乱了:数千个 2008 财年行推高了记录集,而忽略了 COUNT 顺序,并且 2008 年(TOP 1)的结果变得不正确 ,请在此处输入图像描述

然后它恢复正常执行 3 次,依此类推。每当我抹去

SUM(SubTotal)   OVER(Partition BY YEAR(DATEADD(MONTH, 6, OrderDate)) ORDER BY SalesOrderID) RunTotal

从临时表中,订单工作正常。我对这种奇怪的行为感到困惑。

标签: sql

解决方案


没有 .该TOP子句毫无意义ORDER BY。在您的查询中,您是说“从 FiscalYear xxxx 和 RunTotal >= 10000000 的所有结果行中任意选择一行”。这样做的原因是表数据被认为是一组无序的数据。没有ORDER BY就没有保证的顺序。

因此:

SELECT * FROM
(
  SELECT TOP 1 FiscalYear, OrderDate, OrderCount, OrderID, RunTotal
  FROM #data
  WHERE RunTotal >= 10000000 AND FiscalYear = 2007
  ORDER BY RunTotal
) year2007
UNION ALL
SELECT * FROM
(
  SELECT TOP 1 FiscalYear, OrderDate, OrderCount, OrderID, RunTotal
  FROM #data
  WHERE RunTotal >= 10000000 AND FiscalYear = 2008
  ORDER BY RunTotal
) year2008;

我已更改UNIONUNION ALL,因为没有要删除的重复项。

查询结果又是一张表。所以,同样的规则适用:如果你想要一些特定的订单,你需要ORDER BY. 如果您想要 2008 年之前的 2007 年,请添加ORDER BY FiscalYear到查询的末尾。


推荐阅读