2015-02-24 41 views
1

我有一个情况,我需要根据where子句中输入要迭代的情况下,不知道如何可以做到。迭代里面的子查询

的背景是,在一个存储单元,它由几个罐,每个储罐有它自己的坦克倾角测量状态,用不同的最后一次测量的日期,我怎样才能获得特定日期的最新浸价值?

例子:

Tank A having last measured date (EndDate) as 01 Feb 2015. 
Tank B having last measured date (EndDate) as 31 Jan 2015. 
Tank B having last measured date (EndDate) as 17 Feb 2015. 
Tank C having last measured date (EndDate) as 18 Feb 2015. 

表结构:

Tanks| DipDaytime| Volume| EndDate 
A, 28 Jan 2015 8pm, 1000, 01 Feb 2015 
B, 30 Jan 2015 5pm, 2000, 31 Jan 2015 
B, 01 Feb 2015 5pm, 2500, 17 Feb 2015 
C, 01 Feb 2015 3pm, 3000, 18 Feb 2015 

预期输出是:

For 31 Jan 2015: 
A, 28 Jan 2015 8pm, 1000, 01 Feb 2015 
B, 30 Jan 2015 5pm, 2000, 31 Jan 2015 

For 18 Feb 2015: 
A, 28 Jan 2015 8pm, 1000, 01 Feb 2015 
B, 01 Feb 2015 5pm, 2500, 17 Feb 2015 
C, 01 Feb 2015 3pm, 3000, 18 Feb 2015 

我能出来这样的事情:

SELECT ts.Tanks, ts.DipDaytime, ts.EndDate , ts.Volume 
FROM table ts 
WHERE ts.EndDate =  
(SELECT MAX(ts2.EndDate) FROM table ts2 
         WHERE ts2.Tanks = ts.Tanks 
         AND ts2.EndDate <= '17.02.2014') 

问题是我需要改变2014年1月17日每次我需要一个不同的结果对于特定的日期,还我不能显示2014年1月17日作为查询结果的一部分,因为它不是部分表。

我怎么能有它在一个动态的方式在那里我只需要提供一个日期范围,说,来自2014年2月1日至2014年2月28日,以获得完整的结果呢?和显示报告日期的临时列?然后

最终的结果将是:

For 31 Jan 2015: 
Tank | DipDaytime| Volume| EndDate, ReportDate 
A, 28 Jan 2015 8pm, 1000, 01 Feb 2015, 31 Jan 2015 
B, 30 Jan 2015 5pm, 2000, 31 Jan 2015, 31 Jan 2015 

For 18 Feb 2015: 
Tank | DipDaytime| Volume| EndDate, ReportDate 
A, 28 Jan 2015 8pm, 1000, 01 Feb 2015, 18 Feb 2015 
B, 01 Feb 2015 5pm, 2500, 17 Feb 2015, 18 Feb 2015 
C, 01 Feb 2015 3pm, 3000, 18 Feb 2015, 18 Feb 2015 

感激,如果任何人都可以提供帮助。谢谢。

+0

为什么箱体A是出现在两种情况下? – 2015-02-24 11:28:52

+0

@SagarJoon:因为31.01和18.02之间的A罐没有变化? – Andomar 2015-02-24 11:33:09

回答

0

您可以使用row_number()对每(Tank)组最新的行筛选器。使用子查询技巧,您可以使用一个常数都过滤和显示:

select * 
from (
cross join 
     (
     select row_number() over (
        partition by tank 
        order by EndDate desc) as rn 
     ,  * 
     from Tanks 
     cross join 
       (
       select '17.02.2014' as report_date 
       from dual 
       ) pars 
     where EndDate <= report_date 
     ) numbered_rows 
where rn = 1 -- Latest row per tank 

一个更好的方式来使用常量将它作为参数传递给查询。在Oracle中,参数以分号开头,如:report_date

0

你可以尝试这样的:

with report_dates as 
(
    select to_date('31 Jan 2015', 'dd Mon yyyy') report_date from dual 
    union all 
    select to_date('18 Feb 2015', 'dd Mon yyyy') report_date from dual 
) 
select t.tanks, d.report_date, 
     max(t.dipdaytime) keep (dense_rank last order by t.enddate) DipDaytime, 
     max(t.volume) keep (dense_rank last order by t.enddate) volume, 
     max(t.enddate) enddate 
from table t, report_dates d 
where t.dipdaytime <= d.report_date 
group by t.tanks, d.report_date 
order by d.report_date, t.tanks 
; 

这给:

TANKS VOLUME REPORT_DATE DIPDAYTIME ENDDATE 
1 A 1000 31-janv.-2015 28-janv.-2015 01-févr.-2015 
2 B 2000 31-janv.-2015 30-janv.-2015 31-janv.-2015 
3 A 1000 18-févr.-2015 28-janv.-2015 01-févr.-2015 
4 B 2500 18-févr.-2015 01-févr.-2015 17-févr.-2015 
5 C 3000 18-févr.-2015 01-févr.-2015 18-févr.-2015 
0

我会倾向于使用稍微修改您的查询 - 你要定义日期列表,然后在查询中多次使用该列表:

with rd as (
     select date '2015-01-31' as ReportDate from dual 
     union all 
     select date '2015-02-18' from dual 
    ) 
select rd.ReportDate, t.* 
from table t cross join 
    rd 
where t.dipdaytime = (select max(t2.dipdaytime) 
         from table t2 
         where t2.tank = t.tank and 
          t2.dipdaytime <= rd.ReportDate 
        ); 

这是使用相关的子查询来查找每个油箱在任何给定日期之前的最大数量为dipdaytime

0

这个查询给出了一段选定的结果。你必须定义开始报告的日期和截止日期在第一个子查询(dates)。

with dates as (
    select to_date('2015-02-15') + level - 1 tdate 
    from dual 
    connect by to_date('2015-02-15') + level - 1 <= '2015-02-18'), 
tanks as (
    select * 
    from (
     select tdate, tanks, dipdaytime, volume, enddate 
      row_number() over (partition by tanks, tdate order by enddate desc) rn 
     from dates 
     left join ts on ts.enddate <= dates.tdate) 
    where rn = 1) 
select tdate, tanks, dipdaytime, volume 
    from tanks 
    order by tdate, tanks 


TDATE  TANKS  DIPDAYTIME  VOLUME 
----------- ---------- ----------- ---------- 
2015-02-15 A   2015-01-28  1000 
2015-02-15 B   2015-01-30  2000 
2015-02-16 A   2015-01-28  1000 
2015-02-16 B   2015-01-30  2000 
2015-02-17 A   2015-01-28  1000 
2015-02-17 B   2015-02-01  2500 
2015-02-18 A   2015-01-28  1000 
2015-02-18 B   2015-02-01  2500 
2015-02-18 C   2015-02-01  3000 

9 rows selected 

以下查询选择单独列中每个储罐的数据,因此报告期间每个日期都有一行。

with dates as (
    select to_date('2015-02-15') + level - 1 tdate 
    from dual 
    connect by to_date('2015-02-15') + level - 1 <= '2015-02-18'), 
tanks as (
    select * 
    from (
     select tdate, tanks, dipdaytime, volume, enddate, 
      row_number() over (partition by tanks, tdate order by enddate desc) rn 
     from dates 
     left join ts on ts.enddate <= dates.tdate) 
    where rn = 1) 
select dates.tdate, 
    ta.dipdaytime a_ddt, ta.volume a_vol, ta.enddate a_end, 
    tb.dipdaytime b_ddt, tb.volume b_vol, tb.enddate b_end, 
    tc.dipdaytime c_ddt, tc.volume c_vol, tc.enddate c_end 
    from dates 
    left join tanks ta on ta.tdate = dates.tdate and ta.tanks = 'A' 
    left join tanks tb on tb.tdate = dates.tdate and tb.tanks = 'B' 
    left join tanks tc on tc.tdate = dates.tdate and tc.tanks = 'C' 
    order by tdate 

结果:

TDATE  A_DDT   A_VOL A_END  B_DDT   B_VOL B_END  C_DDT   C_VOL C_END 
----------- ----------- ---------- ----------- ----------- ---------- ----------- ----------- ---------- ----------- 
2015-02-15 2015-01-28  1000 2015-02-01 2015-01-30  2000 2015-01-31       
2015-02-16 2015-01-28  1000 2015-02-01 2015-01-30  2000 2015-01-31       
2015-02-17 2015-01-28  1000 2015-02-01 2015-02-01  2500 2015-02-17       
2015-02-18 2015-01-28  1000 2015-02-01 2015-02-01  2500 2015-02-17 2015-02-01  3000 2015-02-18