1

这在理论上很简单,但对我来说很难弄清楚。

我有两个 SQL Server 表:

  1. 带有购买日期和总额的购买清单

    select total, date from purchases
    
  2. 为特定工作和旅行日期旅行的里程列表

    select travelDate, miles from trips
    

编辑:为了保持对我的问题的回答/讨论,我重新表述了这个要求。

我需要计算每次购买之间的总里程数。

我想要比总体平均值更高的准确性。

我可以通过将每个日期trips之间的所有里程相加来手动获取此信息。purchases现在,我只想自动化这个过程。

分组应该使得所有trips大于purchases日期 A 和小于purchases日期 B 的日期都是purchases日期 A 组的一部分。

4

1 回答 1

2

治愈我的密度,我认为您的要求是非常合理的,将问题视为“更换燃料成本” - 因此使用下一次加油的燃料成本而不是之前购买实际使用的燃料的成本(这真的很复杂,真的快速地)。然后音量无关紧要。试穿这个尺寸。

SELECT
   T.*,
   P.*, -- from previous purchase
   N.*, -- from next purchase (NULL if none yet)
   TripCost = N.Total * T.Miles / M.MilesThisFill
FROM
   dbo.Trips T
   CROSS APPLY (
      SELECT TOP 1 *
      FROM dbo.Purchases P
      WHERE P.[Date] < T.travelDate
      ORDER BY P.[Date] DESC
   ) P
   CROSS APPLY (
      SELECT TOP 1 *
      FROM dbo.Purchases P
      WHERE P.[Date] > T.travelDate
      ORDER BY P.[Date]
   ) N
   CROSS APPLY (
      SELECT Sum(miles) MilesThisFill
      FROM dbo.Trips T2
      WHERE
         T2.[Date] > P.[Date]
         AND T2.[Date] < N.[Date]
   ) M;

或者这里有一个版本对问题有非常不同的看法,但应该给出相同的结果。让我知道哪个表现更好,好吗?( SET STATISTICS IO ON; SET STATISTICS TIME ON;)

WITH PSeq AS (
   SELECT
      Seq = Row_Number() OVER (ORDER BY [Date]),
      *
   FROM dbo.Purchases
), Slices AS (
   SELECT
      FromDate = P.[Date],
      ToDate = N.[Date],
      N.Total
   FROM
      PSeq P
      INNER JOIN PSeq N
         ON P.Seq + 1 = N.Seq
), TotalMiles AS (
    SELECT
       S.FromDate,
       Sum(T.Miles) MilesThisFill
    FROM
      Slices S
      INNER JOIN dbo.Trips T
         ON T.travelDate BETWEEN S.FromDate AND S.ToDate
    GROUP BY
       S.FromDate 
)
SELECT
   T.travelDate,
   S.FromDate,
   S.ToDate,
   TripCost = S.Total * T.Miles / M.MilesThisFill
FROM
   Slices S
   INNER JOIN dbo.Trips T
      ON T.travelDate BETWEEN S.FromDate AND S.ToDate 
   INNER JOIN dbo.TotalMiles M
      ON S.FromDate = L.FromDate;

对于任何拼写错误或错误,我提前道歉......我没有测试过代码。

只是为了笑,这是第一个被变形为可以在 SQL Server 2000 上运行的版本的查询!

SELECT
   T.travelDate,
   T.Miles,
   T.ToDate,
   TripCost = P.Total * T.Miles / M.MilesThisFill
FROM
   (
      SELECT
         T.travelDate,
         T.Miles,
         ToDate = (
            SELECT TOP 1 P.Date
            FROM dbo.Purchases P
            WHERE P.[Date] > T.travelDate
            ORDER BY P.[Date]
         )
      FROM
         dbo.Trips T
   ) T
   INNER JOIN (
      SELECT
         ToDate = (
            SELECT TOP 1 P.Date
            FROM dbo.Purchases P
            WHERE P.[Date] > T2.travelDate
            ORDER BY P.[Date]
         ),
         MilesThisFill = Sum(T2.Miles)
      FROM dbo.Trips T2
      GROUP BY
         (
            SELECT TOP 1 P.Date
            FROM dbo.Purchases P
            WHERE P.[Date] > T2.travelDate
            ORDER BY P.[Date]
         )
   ) M ON T.ToDate = M.ToDate
   INNER JOIN dbo.Purchases P
      ON T.ToDate = P.[Date];

这实际上表明我可能不需要在我的第一个查询中查找之前的购买日期,如果我做得对的话......所以这是一个最终版本:

WITH TripData AS (
   SELECT
      T.Miles,
      T.travelDate,
      ToDate = (
         SELECT TOP 1 P.[Date]
         FROM dbo.Purchases P
         WHERE P.[Date] > T.travelDate
         ORDER BY P.[Date]
      )
   FROM
      dbo.Trips T
)
SELECT
   T.*,
   P.*,
   TripCost = P.Total * T.Miles / M.MilesThisFill
FROM
   TripData T
   INNER JOIN dbo.Purchases P
      ON T.ToDate = P.[Date]
   INNER JOIN (
      SELECT
         T2.ToDate,
         Sum(T2.Miles) MilesThisFill
      FROM TripData T2
      GROUP BY
         T2.ToDate
   ) M ON T.ToDate = M.ToDate;

注意: TripCost 表达式的顺序很重要,因为 Miles 和 TotalMiles 是整数。如果你把 P.Total 放在最后,你会得到错误的答案,因为 Miles / TotalMiles 将被转换为整数。

于 2012-08-08T23:35:21.243 回答