我正在尝试使用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中添加了一条记录,以说明报告窗口中没有记录时的预期结果。
答案 0 :(得分: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
但是要理解您的要求有点困难,所以我不确定这对所有情况下的数据都有效。如果您在问题中添加更多数据和预期结果,我可以根据需要进行更新。
评论后修改:
这个新查询给出了您所追求的结果:
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
同样,它仅针对一个小数据集,但它按日期取得最高值而不是最大百分比,所以希望能让你朝着正确的方向前进。
第二次修改:
只需稍微更改查询即可获得新结果:
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
答案 1 :(得分:0)
这是另一种方法:
步骤1。选择行Date
值不晚于所选月份的行,将每个作业的数据拆分为两个分区:所选月份数据进入New
分区其余的进入Old
。
应用于您的示例,这将生成以下结果集:
Job Date Percent_complete recency --- ---- ---------------- ------- 1 1/5/2013 5 Old 2 1/10/2013 5 Old 2 1/25/2013 15 Old 2 2/15/2013 25 New 3 1/15/2013 5 New 1 2/10/2013 10 New 1 2/23/2013 20 New 1 2/24/2013 18 New 4 1/12/2013 40 Old
第2步。按Date
的降序对每个分区中的行进行排名:
Job Date Percent_complete recency rnk --- ---- ---------------- ------- --- 1 1/5/2013 5 Old 1 2 1/10/2013 5 Old 2 2 1/25/2013 15 Old 1 2 2/15/2013 25 New 1 3 1/15/2013 5 New 1 1 2/10/2013 10 New 3 1 2/23/2013 20 New 2 1 2/24/2013 18 New 1 4 1/12/2013 40 Old 1
第3步。仅获取排名为1的行:
Job Date Percent_complete recency rnk --- ---- ---------------- ------- --- 1 1/5/2013 5 Old 1 2 1/25/2013 15 Old 1 2 2/15/2013 25 New 1 3 1/15/2013 5 New 1 1 2/24/2013 18 New 1
第4步。转动百分比并将任何Old
NULL默认为0,将New
默认为Old
:
Job Old New --- --- --- 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
;
您可以测试此查询at SQL Fiddle。