-1

我第一次发帖。

我有一项棘手的任务是在一个范围内查找最新日期,但不包括多个其他日期范围。我有可以工作的代码,但它似乎非常费力。

我在一个范围内选择MAX(Date) 。但是,我有一个表bfShow,其中每个节目都有自己的日期范围(存储为DateStartDateEnd)。所以我需要在那个日期没有节目的范围内的MAX ( Date)(可能有 0 到 99 个节目与我的日期范围重叠)。

注意:我有dbo.fnSeqDates效果很好(通过 Google 找到)并返回一个范围内的所有日期 - 可以非常快速地填写 6/1/12、6/2/12、6/3/12...6 /30/12 等

我正在做的(如下)是创建一个包含所有日期(范围内)的表格,然后找到该范围内的所有节目(#ShowIDs)并遍历这些节目,一次一个,删除所有这些日期(来自#DateRange)。最终,#DateRange 只剩下“空”日期。因此,#DateRange 中剩余的 MAX(Date) 是我本月最后一个没有演出的日期。

同样,我下面的代码确实有效,但必须有更好的方法。想法?

谢谢你,托德

创建过程 spLastEmptyDate
    @DateStart 日期
  , @DateEnd 日期
作为
开始

   -- 变量...
   声明@ShowID int
   声明@EmptyDate 日期

   -- 临时表...
   创建表 #DateRange(dDate 日期)
   创建表 #ShowIDs(ShowID int)

   -- 加载范围内的所有日期(本月-ISH)...
   插入#DateRange(dDate)
   选择 SeqDate
   来自 dbo.fnSeqDates(@DateStart, @DateEnd)

   -- 加载范围内的所有节目 ID(本月)...
   插入#ShowIDs(ShowID)
   选择 s.ShowID
   来自 bfShow 的
   其中 s.DateStart = @DateStart

   -- PRIME SHOW ID...
   设置@ShowID = 0
   选择@ShowID = min(ShowID)
   来自#ShowIDs

   -- 全部运行,删除日期...
   而(@ShowID > 0)
   开始
      -- 从温度中移除...
      删除 DR
      来自#DateRange DR
         , bfShow s
      其中 s.DateStart 和 s.DateEnd 之间的 DR.dDate
        和 s.ShowID = @ShowID

      -- 从 TEMP 中删除那个...
      从#ShowIDs 中删除
      其中 ShowID = @ShowID

      -- 获取下一个 ID...
      设置@ShowID = 0
      选择@ShowID = min(ShowID)
      来自#ShowIDs
   结尾

   -- 获取最后一个空位...
   选择@EmptyDate = max(dDate)
   来自#DateRange

   -  清理...
   删除表#DateRange
   删除表 #ShowIDs

   -- 返回数据...
   选择 @EmptyDate 作为 LastEmptyDateInRange

结尾
4

2 回答 2

0

让我们知道您使用的是哪个版本的 SQL Server,因为这将有助于确定您的选择,但您应该能够在 fnSeqDates 函数之间的 JOIN 中使用 BETWEEN 运算符(它是一个表值函数,因此您可以加入它直接而不是将它们插入临时表)和 bfShow 表:

SELECT TOP 1 tDate.SeqDate
FROM dbo.fnSeqDates('6/1/2012', '6/30/2012') tDate
    LEFT JOIN bfShow tShow
        ON tDate.SeqDate BETWEEN tShow.DateStart AND tShow.DateEnd
WHERE tShow.ShowID IS NULL -- no matches found
ORDER BY tDate.SeqDate DESC -- to pull the most recent date
于 2012-06-19T06:07:33.007 回答
0

好的,我想我会重新表述这个问题,并尝试公开一些极端情况。我根本没有使用你的功能。如果这不正确,你能举一个失败的例子吗?

create table bfShow (
    DateStart date,
    DateEnd date
)
go
CREATE procedure spLastEmptyDate
    @DateStart date
  , @DateEnd   date
as
    --Return @DateEnd, or, if that is within a show, find the contiguous
    --region of shows covering it, and select the day before that
    ;with ShowsCovering as (
        select DateStart,DateEnd from bfShow where DateStart <= @DateEnd and DateEnd >= @DateEnd
        union all
        select s1.DateStart,s2.DateEnd
        from
            bfShow s1
                inner join
            ShowsCovering s2
                on
                    s1.DateStart < s2.DateStart and
                    (
                        --This join would be helped by an indexed computed column on bfShow, either Start-1 or End+1
                        s1.DateEnd >= s2.DateStart or
                        s1.DateEnd = DATEADD(day,-1,s2.DateStart)
                    )
        where
            s2.DateStart > @DateStart
    ), Earliest as (
        select MIN(DateStart) as MinDate from ShowsCovering
    )
    --1) If there are no rows, the answer is @DateEnd
    --2) If there are rows, and the MIN(DateStart) = @DateStart, then no day exists
    --3) Otherwise, the answer is MIN(DateStart)-1
    , Answer as (
        select @DateEnd as Result where exists(select * from Earliest where MinDate is null)
        union all
        select DATEADD(day,-1,MinDate) from Earliest where MinDate > @DateStart
    )
    select Result from Answer
go
insert into bfShow(DateStart,DateEnd)
values ('20120601','20120612'),
('20120619','20120630')
go
exec spLastEmptyDate '20120601','20120625'
--Result = 2012-06-18
go
exec spLastEmptyDate '20120525','20120625'
--Result = 2012-06-18
go
exec spLastEmptyDate '20120601','20120705'
--Result = 2012-07-05
go
insert into bfShow(DateStart,DateEnd)
values ('20120613','20120618')
go
exec spLastEmptyDate '20120601','20120625'
--Result - no rows

顺便说一句,在您当前的解决方案中,这些行:

drop table #DateRange
drop table #ShowIDs

是不必要的。当存储过程退出时,在存储过程中创建的临时表会被自动删除。select max(dDate) as LastEmptyDateInRange from #DateRange因此,如果您想继续使用您的解决方案,您可以避免最后的小舞并制作最后一行。

于 2012-06-19T07:17:49.573 回答