2015-12-31 5 views
5

私はプロジェクトのデータセットを持っています。プロジェクトの状態が最初から最後に変わり、ステータス変更の日付がテーブルに記録されます(テーブルの名前は「イベント」 - 私の選択ではありません)。このようになります(簡体字):任意の日付範囲でMySQL所定のステータスの2つの日付の間に不足する日付を入力してください

Date  Status 
2015-06-01 Start 
2015-06-03 Stage 2 
2015-06-07 Stage 3 

は(動的に決定されるように)私はどの状態にあるどのプロジェクトを参照することができるようにしたいです。ただし、データに対してBETWEENまたは他のクエリを使用すると、ステータスがに変更されたプロジェクトは、その期間中にに変更されます。一定のステータスには変更されません。

Date   Status 
2015-06-01 Project start 
2015-06-02 Project start (copied) 
2015-06-03 Stage 2 
2015-06-04 Stage 2 (copied) 
2015-06-05 Stage 2 (copied) 
2015-06-06 Stage 2 (copied) 
2015-06-07 Stage 3 

このソリューションは言う、私は上のプロジェクトのステータスを照会することができます:

は、私は現在、そのような状態変更の日付の間に新しい行、にコピーの行がどのExcelで非常に不格好なソリューションを作成しました、2015年6月6日と、それは段階でまだ2

であることがわかり、私はこの同じデータをプルするためにMySQLを使用することができますいくつかの方法がありますが、出力としてクエリに?私は、カレンダーテーブルを使用することを提案していると聞いてきましたが、どのように動作するのか分かりません。私は誰かがクロス結合を推薦しているのを見たことがありますが、再び、どのように動作するか説明から理解できませんでした。

ご協力いただきありがとうございます。

答えて

0

すべての日付の表を作成する必要はありません。テーブルを変更して各ステータスの開始日と終了日を指定し、betweenステートメントを使用することができます。

たり、既存のデータを使用して。

ステータスを確認したい日付として@Datequeryを使用しています。

Select top 1 Status from Events 
where Date <= @datequery and Date 
order by Date desc 

は、照会している日付の前に最新のステータス変更を返します。

@datequery = 2015-06-06 

Status 
Stage 2 
1

計画

  • クロス接合桁カレンダーテーブルを作成し、カレンダ期間にわたってDATE_ADD ..
  • 状態

セットアップ

を取得するために、元のデータソースへの参加日の日付< =カレンダーの日付
  • テイク最大< =カレンダーの日付
  • とカレンダーのソースに、あなたのデータを結合
    drop table if exists calendar_t; 
    CREATE TABLE calendar_t (
        id integer primary key auto_increment not null, 
        `date` date not null, 
        day varchar(9) not null, 
        month varchar(13) not null, 
        `year` integer not null 
    ); 
    
    drop view if exists digits_v; 
    create view digits_v 
    as 
    select 0 as n 
    union all 
    select 1 
    union all 
    select 2 
    union all 
    select 3 
    union all 
    select 4 
    union all 
    select 5 
    union all 
    select 6 
    union all 
    select 7 
    union all 
    select 8 
    union all 
    select 9 
    ; 
    
    insert into calendar_t 
    (`date`, day, month, `year`) 
    select 
    date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day) as `date`, 
    dayname(date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day)) as day, 
    monthname(date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day)) as month, 
    year(date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day)) as `year` 
    from 
    digits_v a2 
    cross join digits_v a1 
    cross join digits_v a0 
    order by date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day) 
    ; 
    
    drop table if exists example; 
    create table example 
    (
        `date` date not null, 
        status varchar(23) not null 
    ); 
    
    insert into example 
    (`date`, status) 
    values 
    ('2015-06-01', 'Start' ), 
    ('2015-06-03', 'Stage 2'), 
    ('2015-06-07', 'Stage 3') 
    ; 
    

    クエリ

    select cal_date, mdate, ex2.status 
    from 
    (
    select cal_date, max(ex_date) as mdate 
    from 
    (
    select cal.`date` as cal_date, ex.`date` as ex_date 
    from calendar_t cal 
    inner join example ex 
    on ex.`date` <= cal.`date` 
    ) maxs 
    group by cal_date 
    ) m2 
    inner join example ex2 
    on m2.mdate = ex2.`date` 
    -- pick a reasonable end date for filtering.. 
    where cal_date <= date('2015-06-15') 
    order by cal_date 
    ; 
    

    出力

    +------------------------+------------------------+---------+ 
    |  cal_date  |   mdate   | status | 
    +------------------------+------------------------+---------+ 
    | June, 01 2015 00:00:00 | June, 01 2015 00:00:00 | Start | 
    | June, 02 2015 00:00:00 | June, 01 2015 00:00:00 | Start | 
    | June, 03 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 | 
    | June, 04 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 | 
    | June, 05 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 | 
    | June, 06 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 | 
    | June, 07 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 08 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 09 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 10 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 11 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 12 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 13 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 14 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    | June, 15 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 | 
    +------------------------+------------------------+---------+ 
    

    sqlfiddle


    参照

  • +0

    おかげで、amdixon。私はオフィスに戻ってきたときにそれを撃つだろう。その間に、私はそれが意味するものを理解するために働くでしょう:)私は以前にクロスジョインを使ったことがなく、彼らが何のために使われたのか疑問に思いました。私は、私が見つけようとしていると思う。 –

    +0

    クロス結合とは、左右のデータセットのすべてのレコードの組み合わせを意味します。したがって、5レコードのデータセットで2レコードのデータセットを結合すると、10レコードのデータセットが作成されます。 [クロスジョイン](http://www.w3resource.com/sql/joins/cross-join.php)をチェックしてください。このコンテキストでは、数値シーケンスを生成する方法です。 – amdixon

    +0

    @RyanVincentはい、これをカレンダーの集計のための(シーケンス生成のための)容易に利用可能なデータソースとして使用できます。カレンダーの負荷は最大1年に1回しか発生しないため、効率はおそらく問題ではありません。 idシーケンスに隙間がないことを確認してください。 – amdixon

    関連する問題