这在理论上很简单,但我很难弄明白。
我有两个SQL Server表:
购买日期和总数
的购买清单select total, date from purchases
特定工作和旅行日期的行驶里程列表
select travelDate, miles from trips
编辑:为了保留我的问题的答案/讨论,我正在重新阐述这一要求。
我需要弄清楚每次购买之间的总里程数。
我想要比整体平均值更准确。
我可以通过在每个trips
日期之间总结purchases
的所有里程来手动获取此值。现在,我只想自动化这个过程。
分组应该是所有trips
日期大于purchases
日期A且小于purchases
日期B都是purchases
日期A组的一部分。
答案 0 :(得分: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将转换为整数。