2

MSSQL 2008を使用して、指定された日付ウィンドウで実行中の(より適切な用語がないため)値の最も古い値と最も新しい値を取得しようとしていますが、苦労しています。テーブルは次のようになります。

Job      Date         Percent_complete
---      ----         ----------------
1        1/5/2013     5
2        1/10/2013    5
2        1/25/2013    15
2        2/15/2013    25
3        2/15/2013    5
1        2/10/2013    10
1        2/23/2013    20
1        2/24/2013    18
4        1/12/2013    40

たとえば、私のクエリでは、2013年2月1日から2013年2月28日までの最も古いおよび最新のpercent_completeを要求し、次のように取得します。

Job   Old    New
---   ---    ---
1     5      18
2     15     25
3     0      5
4     40     40

...したがって、ここでの問題は、開始日の前の最後のpercent_complete値を繰り越す必要があり、レコードがない場合(ジョブ3など)は0と見なす必要があることです。さらに、数値は高い値から後退する可能性があります。 、ジョブ1の場合と同じように、...だからmin(complete)、そこに到達しmax(complete)ません。また、レポートウィンドウにレコードがない場合に期待される結果を示すために、ジョブ4のレコードを追加しました。

4

2 に答える 2

2

私はこのようなもので結果を得ることができます:

with max_percent as
(
  select Job
    , [Max] = max(Percent_complete)
  from jobs
  where [Date] between '2/1/2013' and '2/28/2013'
  group by Job
),
min_percent as
(
  select Job
    , [Max] = max(Percent_complete)
  from jobs
  where [Date] < '2/1/2013'
  group by Job
)
select Job = coalesce(mn.Job, mx.Job)
  , [Min] = case when mx.Job is not null then mn.[Max] else 0 end
  , [Max] = coalesce(mx.[Max], mn.[Max], 0)
from max_percent mx
  full join min_percent mn on mx.Job = mn.Job
order by Job

SQLFiddleデモ

ただし、要件を理解するのは少し難しいので、これがすべての場合にデータに対して機能するかどうかはわかりません。質問にさらにデータと期待される結果を追加すると、必要に応じて更新できます。

コメント後に編集:

この新しいクエリは、あなたが求めている結果を提供します。

with jobList as
(
  select distinct Job from jobs
)
select Job
  , [Min] = isnull(case when mx.[Max] is not null then mn.[Max] else 0 end, 0)
  , [Max] = coalesce(mx.[Max], mn.[Max], 0)

from jobList jl
  outer apply
  (
    select top 1 [Max] = j.Percent_complete
    from jobs j
    where [Date] between '2/1/2013' and '2/28/2013'
      and jl.Job = j.Job
    order by j.[Date] desc
  ) mx
  outer apply
  (
    select top 1 [Max] = j.Percent_complete
    from jobs j
    where [Date] < '2/1/2013'
      and jl.Job = j.Job
    order by j.[Date] desc
  ) mn
order by jl.Job

デモ付きのSQLフィドル

繰り返しになりますが、これは小さなデータセットに対してのみですが、最大パーセンテージだけでなく、日付ごとに上位の値を取得するため、正しい方向に進むことができれば幸いです。

2番目の編集:

クエリを少し変更するだけで、新しい結果が得られます。

with jobList as
(
  select distinct Job from jobs
)
select Job
  , [Min] = isnull(mn.[Max], 0)
  , [Max] = coalesce(mx.[Max], mn.[Max], 0)

from jobList jl
  outer apply
  (
    select top 1 [Max] = j.Percent_complete
    from jobs j
    where [Date] between '2/1/2013' and '2/28/2013'
      and jl.Job = j.Job
    order by j.[Date] desc
  ) mx
  outer apply
  (
    select top 1 [Max] = j.Percent_complete
    from jobs j
    where [Date] < '2/1/2013'
      and jl.Job = j.Job
    order by j.[Date] desc
  ) mn
order by jl.Job

デモ付きのSQLフィドル

于 2013-02-13T22:52:58.463 に答える
0

別のアプローチは次のとおりです。

手順1.選択した月までに値を持つ行を選択しDate、すべてのジョブのデータを2つのパーティションに分割します。選択した月のデータはNewパーティションに入れられ、残りはOld1つのパーティションに入れられます。

あなたの例に適用すると、これは次の結果セットを生成します:

Job Date Percent_complete   recency 
--- ---- ----------------   ------- 
1 1/5/2013 5                  Old     
2 1/10/2013 5                  Old     
21/25/201315                古い    
22/15/201325                新しい    
31/15/20135                 新しい    
12/10/201310新しい    
12/23/201320                新しい    
12/24/201318                新しい    
41                 2013年12月40日40                

手順2.すべてのパーティションの行を次の降順でランク付けしますDate

Job Date Percent_complete   recency rnk 
--- ---- ---------------- -------   --- 
1 1/5/2013 5 Old       1   
2 1 / 10/20135古い      221/25/201315  
古い      122/15/201325  
新しい      131/15/20135  
新しい      112/10/201310  
新しい      312/23/201320  
新しい      2   
12/24/201318新しい      141/12/201340  
古い      1  

ステップ3.1のランキングの行のみを取得します。

Job Date Percent_complete recency rnk
--- ---- ---------------- ------- ---
12013年1月5日5古い1
21/25/201315古い1
22013年2月15日25新規1
32013年1月15日5新規1
12013年2月24日18新規1

ステップ4.パーセンテージをピボットし、デフォルトでOldNULLを0に設定し、次のように設定NewOldます。

仕事古い新しい
--- --- ---
1 5 18
2 15 25
3 05

次のクエリは、上記のロジックを実装します。

WITH partitioned AS (
  SELECT
    Job,
    Date,
    Percent_complete,
    recency = CASE
      WHEN Date >= '20130201' THEN 'NEW'
      ELSE 'Old'
    END
  FROM atable
  WHERE Date < '20130301'
)
, ranked AS (
  SELECT
    Job,
    Date,
    Percent_complete,
    recency,
    rnk = ROW_NUMBER() OVER (PARTITION BY Job, recency ORDER BY Date DESC)
  FROM partitioned
)
, filtered AS (
  SELECT
    Job,
    Percent_complete,
    recency
  FROM ranked
  WHERE rnk = 1
)
, pivoted AS (
  SELECT
    Job,
    Old = ISNULL(Old, 0),
    New = ISNULL(New, Old)
  FROM filtered
  PIVOT (
    MAX(Percent_complete) FOR recency IN (Old, New)
  ) u
)
SELECT *
FROM pivoted
;

このクエリはSQLFiddleでテストできます。

于 2013-02-21T18:50:08.600 に答える