如何使用SQL在日期之间进行求和?

时间:2010-06-29 09:34:10

标签: sql visual-studio-2008 sql-server-2005

请看下面的 UPDATED 方案(很遗憾,我用非更新版本欺骗了你 - 希望现在更清楚了) - 对某些人来说这似乎很简单,希望它是! / p>

说明:每一行都是一个请求。分配的是活动请求的人数,总数是此国家/地区可用于活动的总人数,差异是...总人数与最大人数之间的差异。 并且“最多人使用......”就是其他所有内容。

SHOULD BE:                      

COLLECTION OF REQUESTS WITH DIFFERENT START- AND END DATES

COUNTRY START DATE  END DATE    ALLOCATED   TOTAL    Max people used for this period    DIFF
China     NOV 1       NOV 2       2           5         4                                 1
China     NOV 3       NOV 4       2           5         4                                 1
China     NOV 1       NOV 4       2           5         4                                 1


MY RESULT:

COLLECTION OF REQUESTS WITH DIFFERENT START- AND END DATES

COUNTRY START DATE  END DATE    ALLOCATED   TOTAL    Max people used for this period    DIFF
China     NOV 1       NOV 2       2           5         4                                 1
China     NOV 3       NOV 4       2           5         4                                 1
China     NOV 1       NOV 4       2           5         6                                -1

(For NOV 1 to NOV 4 "Max people used..." sums ALLOCATED as 2+2+2 instead of 2+2...)

在这里你可以看到我是如何得到“我的结果”

SELECT DISTINCT Country.Country,
-- here comes the sum that doesn´t work...
SUM(Requests.[Amount of people per day needed]) AS [Max people used for this period]
FROM         Country INNER JOIN
                      Requests ON Country.CountryID = Requests.CountryID
WHERE     (Country.Country = 'China')
AND (Requests.[End date] >= @busyStartDate)
AND (Requests.[Start date] <= @busyEndDate)
GROUP BY Country.Country

“最多人使用......”是不能在这里工作的东西 - 我可以做到这一点,其余的将遵循你在这里看不到的业务逻辑: - )

更新

实际上,我已经放弃了这一点 - 尽管有很好的答案,却没有让它发挥作用。相反,我做了this(当然是在其他人的帮助下)最终达到我的目标; - )

2 个答案:

答案 0 :(得分:1)

一体化多重CTE解决方案(感谢Martin!)

with AllDates as (
  select  StartDate as [day] from Request
  union
  select  Enddate as [day] from Request),
TotalUsage as (
  select  [day], sum(allocated) as TotalAllocated
    from  AllDates
    join  Request
      on  [day] between StartDate and EndDate
    group by [day]),
MaxPerRequest as (
  select  CountryId, StartDate, EndDate, Allocated, MAX(TotalAllocated) as MaxAllocated
    from  Request
    join  TotalUsage
      on  [day] between StartDate and EndDate
    group by CountryId, StartDate, EndDate, Allocated
    )
select StartDate, EndDate, Allocated, MaxAllocated, Country.People - MaxAllocated as Diff
  from MaxPerRequest
  join Country on MaxPerRequest.CountryId = Country.CountryId

旧临时表解决方案

唉我认为你不能嵌套CTE,所以你需要像

这样的东西
with alldates as (
  select StartDate as [day] from request
  union
  select EndDate as [day] from request)
select [Day], sum(allocated) as TotalAllocated
into #TotalUsage
from alldates
join request on [Day] between StartDate and EndDate
group by [Day];

将所有有趣日期的每日分配总数构建到临时表中。 (我永远不记得哪个是SQL Server最好的临时表机制对不起 - 最好使用表变量,并且可能需要添加索引+键。)然后,您可以从中选择max(TotalAllocated)对于给定的日期范围。

with MaxPerRequest as (
  select CountryID, StartDate, EndDate, Allocated, MAX(TotalAllocated) as MaxAllocated
    from request
    join #TotalUsage
      on [DAY] between StartDate and EndDate
    group by CountryID, StartDate, EndDate, Allocated
    )
select StartDate, EndDate, Allocated, MaxAllocated, Country.People - MaxAllocated as Diff
  from MaxPerRequest
  join Country on MaxPerRequest.CountryID = Country.CountryID

drop table #TotalUsage

抱歉,我想不出更简单的解决方案。

答案 1 :(得分:1)

我认为您需要的搜索条件如下所示:

SELECT *
  FROM MyTable AS T1
 WHERE CASE 
          WHEN @start_date > T1.start_date THEN @start_date 
          ELSE T1.start_date 
       END 
       < 
       CASE 
          WHEN @end_date > T1.end_date THEN T1.end_date 
          ELSE @end_date 
       END;

...但我会对您的数据做出许多假设,以便提出更多信息,例如:你在使用闭合开放表示,你使用DATETIME值等吗?

时态数据库设计非常难以正确,如果您的SQL DDL不正确,那么您的SQL DML确实非常棘手。一本关于这个主题的好书是由Rick Snodgrass撰写的Developing Time-Oriented Database Applications in SQL,可以免费下载PDF格式。