带子查询的SQL Case语句

时间:2014-04-07 19:10:57

标签: sql sql-server

我正在尝试编写一个查询来报告在特定月份内部件的使用次数。例如,将二月作为报告月份。如果P1在2014-02-05之前安装在A1上,并且在2014-02-01至2014-02-05之间使用,那么我需要总结一下。此外,如果P1安装在A2上,那么我需要总结使用情况,直到2014-02-28。

| part | date_trans | transaction | unit |
---------------------------------------------
  p1     2014-02-05    removed        A1
  p1     2014-02-07    installed      A2

| unit | daily usage | date |
   A1       3         2014-02-01
   A1       2         2014-02-03
   A2       2         2014-02-05
   A2       4         2014-02-08
   A2       2         2014-02-20

记录的通知

| unit | daily usage | date |
  A2       2         2014-02-05

我们不需要考虑因为2014年2月2日未在A2上安装P1。

到目前为止,这是我的尝试..

SELECT     
CASE
WHEN h.date_trans between '2014-01-31' and '2014-02-28' and transaction='removed' THEN...
END AS 'test'
FROM history h join acu on(acu.unit=h.unit)
WHERE h.part='P1'

2 个答案:

答案 0 :(得分:0)

像这样。

/*
create table #t1 (part char(2), date_trans date, trans char(10), unit char(2))
go
insert #t1 values
('p1',     '2014-02-05',    'removed'  ,      'A1'),
('p1',     '2014-02-07' ,   'installed',      'A2')
go
create table #t2 (unit char(2), usage int, dt date)
go
insert #t2 values
(   'A1',       3,         '2014-02-01'),
(   'A1',       2,         '2014-02-03'),
(   'A2',       2,         '2014-02-05'),
(   'A2',       4,         '2014-02-08'),
(   'A2',       2,         '2014-02-20')
*/


declare @min date = '20140201', @max date = '20140228'
;with x as (
    select *,
    isnull(case trans when 'removed' then lag(date_trans) over(partition by part order by date_trans) else date_trans end, @min) as date_start,
    isnull(case trans when 'installed' then lead(date_trans) over(partition by part order by date_trans) else date_trans end, @max) as date_end
    from #t1
)
select #t2.unit, x.part, sum(#t2.usage)
from #t2
inner join x on #t2.dt between x.date_start and x.date_end
and x.unit = #t2.unit
group by #t2.unit, x.part

-- drop table #t1, #t2

以下是旧版(2012年之前)版本的查询:

;with x as (
    select *, row_number() over(partition by part order by date_trans) as rn
    from #t1
),
y as (
    select x1.*,
    case x1.trans when 'removed' then isnull(x2.date_trans, @min) else x1.date_trans end as date_start,
    case x1.trans when 'installed' then isnull(x3.date_trans, @max) else x1.date_trans end as date_end
    from x x1
    left outer join x x2 on x1.rn = x2.rn+1
    left outer join x x3 on x1.rn = x3.rn-1
)
select #t2.unit, y.part, sum(#t2.usage)
from #t2
inner join y on #t2.dt between y.date_start and y.date_end
and y.unit = #t2.unit
group by #t2.unit, y.part

答案 1 :(得分:0)

您可以使用CTE尝试以下查询:

with history_installed as
(select part, 
case
  when date_trans <= '2014-02-01' then '2014-02-01'
  else date_trans 
end date_trans
from history
where transaction = 'installed' and date_trans < '2014-03-01') 
, history_removed as
(select part, 
case
  when date_trans >= '2014-02-28' then '2014-02-28'
  else date_trans
end date_trans
from history
where transaction = 'removed' and date_trans >= '2014-02-01')
select acu.*
from acu
inner join history_installed on history_installed.date_trans <= acu.date
inner join history_removed on history_removed.date_trans >= acu.date