Sql server 2008 如何按表B中的日期对表A中的SQL Server行进行分组

Sql server 2008 如何按表B中的日期对表A中的SQL Server行进行分组,sql-server-2008,Sql Server 2008,这在理论上很简单,但对我来说很难理解 我有两个SQL Server表: 包含采购日期和总金额的采购清单 select total, date from purchases 特定工作和旅行日期的旅行里程列表 select travelDate, miles from trips 编辑:为了保留对我问题的回答/讨论,我重新表述了要求 我需要计算出每次购买之间的总行驶里程 我想要比总体平均水平更准确的数据 我可以通过对每次购买日期之间的行程的所有英里数求和来手动获取该值。现在,我只想自动化这个

这在理论上很简单,但对我来说很难理解

我有两个SQL Server表:

  • 包含采购日期和总金额的采购清单

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

    select travelDate, miles from trips
    
  • 编辑:为了保留对我问题的回答/讨论,我重新表述了要求

    我需要计算出每次购买之间的总行驶里程

    我想要比总体平均水平更准确的数据

    我可以通过对每次
    购买
    日期之间的
    行程
    的所有英里数求和来手动获取该值。现在,我只想自动化这个过程


    分组应确保所有
    行程
    日期大于
    采购
    日期A且小于
    采购
    日期B的行程都是
    采购
    日期A组的一部分。

    鉴于我的密集性,我认为您的要求是相当合理的,将问题视为“更换燃料成本”-因此,使用下一次加油的燃油成本而不是以前的成本来购买实际使用的燃油(这变得非常复杂,非常快)。那么音量就无关紧要了。试试这个尺码

    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;
    
    我为任何打字错误或错误提前道歉。。。我还没有测试代码

    笑一下,这是第一个被转化为甚至可以在SQLServer2000上运行的查询版本

    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放在最后,你会得到错误的答案,因为英里/总英里将被转换成一个整数。

    各种连接和求和,甚至没有什么能让我接近。我想我可以从一开始就弄清楚,但是没有一个结果是有用的。我不是想含糊其辞,我只是没有得到任何有用的东西。在Excel中,我会做一个Vlookup,因为它会找到最接近的次最小值。你的模型是基于油箱每次都被完全清空的假设吗?这里简单计算
    [每次行程英里数]/[自上次购买以来的所有行程英里数]*[上次购买的总里程数]
    的问题在于,当移动车辆“花费”上次购买的每单位价格时,上次购买的金额中嵌入了数量。为了正确计算,我们还需要购买的“加满加仑/升”,包括旅行后的下一次购买!(续)如果一次购买仅为半个油箱,但下一次购买之前的所有行程都将油箱完全排空,则每次行程的成本将非常低,根本无法反映实际成本。半满油箱更为复杂,因为事实上一半的燃油是新价格,一半是旧价格。。。甚至有可能是在那之前和那之前在油箱里的燃料。所有这些事实上都可以解释,但我们需要每次加油的体积来处理数据。假设每次加油时油箱都满了(他们会这样做),那么如果我花50美元买汽油跑100英里,那么不管我实际使用了多少燃料,这100英里每英里的成本都是0.50美元。除此之外,我正在寻找一种方法,通过
    购买
    记录,将
    旅行
    记录与下一个最近的最小日期分组。让我们换一种方式来描述它,并说我想得到每次
    购买
    记录之间发生的
    旅行
    记录的计数。这看起来非常有希望。我不明白你为什么要从
    P
    中选择两次all。我遗漏了什么吗?@davids这只是一个输入错误,请查看我的更新。你甚至可能不需要所有这些数据——只是一个例子。这正是我需要给我指出的正确方向。谢谢对于反馈,切片方法似乎产生了最准确的结果(在我将其分解以理解之后)。最后一种方法最简单,但结果并不完全正确。这可能主要是因为我的live db比我提供的简单示例复杂得多。@davids他们应该给出相同的结果。但我做了一些不同的事情:我使用
    进行一些查询,而
    =
    进行其他查询(也称为
    之间的
    )。如果将其他查询调整为使用包含端点,是否会获得更好的结果?另外,我在第二个问题中输入了一个可怕的错误应该是P.Seq+1=N.Seq上的
    (现在更新)。请建议…@davids还有一件事:使用包含开始和结束日期可能是错误的。如果任何行程与购买的确切日期匹配,则该行程将计入之前和下一次购买,这是不正确的。
    
    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;