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

例如,在我的查询中,我想询问 2/1/2013 - 2/28/2013 最旧和最新的 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)让我们到达那里。此外,我还为 Job 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

SQL 小提琴演示

但是理解您的要求有点困难,所以我不确定这是否适用于所有情况下的数据。如果您在问题中添加更多数据和预期结果,我可以根据需要进行更新。

评论后编辑:

这个新查询给出了您所追求的结果:

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 Fiddle 与演示

同样,它只针对一个小数据集,但它按日期取最高值,而不仅仅是最大百分比,所以希望能让你朝着正确的方向前进。

第二次编辑:

只需稍微更改查询即可获得新结果:

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 Fiddle 与演示

于 2013-02-13T22:52:58.463 回答
0

这是另一种方法:

步骤 1.选择Date值不晚于所选月份的行,将每个作业的数据分成两个分区:所选月份数据进入New分区,其余进入分区Old

应用于您的示例,这将产生以下结果集:

工作日期 Percent_complete  新近度
--- ---- ---- --------   1 1/5/2013 
5                 
2 1/10/2013 5                 
2 1/25/2013 15                
2 2/15/2013 25                
3 1/15/2013 5                 
1 2/10/2013 10                
1 2/23/2013 20                
1 2/24/2013 18                
4 1 /12/2013 40                

步骤 2.按降序排列每个分区中的行Date

工作日期 Percent_complete 新近度  rnk 
--- ---- ---- --------   --- 
1 1/5/2013 5 旧      1   
2 1/ 10/2013 5 旧      2   
2 1/25/2013 15 旧      1   
2 2/15/2013 25 新      1   
3 1/15/2013 5 新      1   
1 2/10/2013 10 新      3   
1 2/23/2013 20 新      2   
1 2013 年 2 月 24 日 18 新      1   
4 2013 年 1 月 12 日 40 旧      1  

步骤 3.仅获取排名为 1 的行:

工作日期 Percent_complete 新近度 rnk
--- ---- ---- -------- ---
1 2013 年 1 月 5 日 5 旧 1
2 2013 年 1 月 25 日 15 旧 1
2 2013 年 2 月 15 日 25 新 1
3 2013 年 1 月 15 日 5 新 1
1 2013 年 2 月 24 日 18 新 1

步骤 4.将百分比和默认任何OldNULL 设置为 0,并New设置为Old

工作 旧 新
--- --- ---
1 5 18
2 15 25
3 0 5

以下查询实现了上述逻辑:

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
;

您可以在 SQL Fiddle测试此查询。

于 2013-02-21T18:50:08.600 回答