-1

初めての投稿。

範囲内の最新の日付を見つけるというトリッキーなタスクがありますが、他の複数の日付範囲を除外します。私は機能するコードを持っています、それはひどく負担がかかるようです。

範囲内のMAX(日付)を選択しています。ただし、テーブルbfShowがあり、各ショーには独自の日付範囲があります(DateStartおよびDateEndとして保存されます)。したがって、その日付にショーがない範囲内のMAX(日付)が必要です(0から99のショーが私の日付範囲と重複している可能性があります)。

注:私はdbo.fnSeqDatesを持っています。これは(Googleで見つかりました)うまく機能し、範囲内のすべての日付を返します-6/1 / 12、6 / 2 / 12、6 / 3/12...6で非常に高速に入力できます/30/12など

私が行っているのは(以下)、すべての日付(範囲内)を含むテーブルを作成し、その範囲内のすべてのショー(#ShowIDs)を見つけて、それらのショーを一度に1つずつ繰り返し、すべての日付を削除することです。 (#DateRangeから)。最終的に、#DateRangeには「空の」日付のみが残ります。したがって、#DateRangeに残っているMAX(Date)は、ショーがない月の最後の日付です。

繰り返しますが、以下の私のコードは機能しますが、より良い方法が必要です。考え?

ありがとう、トッド

CREATEプロシージャspLastEmptyDate
    @Date開始日
  、@ DateEnd date
なので
始める

   --VARS..。
   @ShowIDintを宣言します
   @EmptyDate日付を宣言します

   --TEMP TABLE .. ..
   テーブルの作成#DateRange(dDate date)
   テーブルの作成#ShowIDs(ShowID int)

   -すべての日付を範囲内でロードします(今月のように)...
   #DateRange(dDate)に挿入
   SeqDateを選択します
   dbo.fnSeqDates(@ DateStart、@ DateEnd)から

   -すべてのショーIDを範囲内にロードします(今月-IS)..
   #ShowIDs(ShowID)に挿入
   s.ShowIDを選択します
   bfShowから
   ここで、s.DateStart = @DateStart

   --PRIME SHOW ID .. ..
   @ShowID=0に設定
   @ShowID = min(ShowID)を選択します
   #ShowIDsから

   -すべてを実行し、日付を削除します...
   while(@ShowID> 0)
   始める
      -臨時雇用者から削除...
      DRを削除する
      #DateRangeDRから
         、bfShow s
      ここで、s.DateStartとs.DateEndの間のDR.dDate
        およびs.ShowID=@ShowID

      --TEMPからその1つをドロップします。
      #ShowIDsから削除
      ここで、ShowID = @ShowID

      -次のIDを取得...
      @ShowID=0に設定
      @ShowID = min(ShowID)を選択します
      #ShowIDsから
   終わり

   -最後の空のスポットを取得...
   @EmptyDate = max(dDate)を選択します
   #DateRangeから

   -  掃除...
   ドロップテーブル#DateRange
   ドロップテーブル#ShowIDs

   -データを返す..。
   LastEmptyDateInRangeとして@EmptyDateを選択します

終わり
4

2 に答える 2

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 に答える
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 に答える