我正在查询特定对象的最近10天的数据:
AMT READING_TIME DATE
-----------------------------------------------------
12-MAR-15 12:00:00 AM
11-MAR-15 12:00:00 AM
10-MAR-15 12:00:00 AM
24545 09-MAR-15 10:54:00 AM 09-MAR-15 12:00:00 AM
24549 08-MAR-15 09:51:00 PM 08-MAR-15 12:00:00 AM
24549 07-MAR-15 11:37:00 PM 07-MAR-15 12:00:00 AM
24549 06-MAR-15 10:08:00 PM 06-MAR-15 12:00:00 AM
24556 05-MAR-15 11:35:00 PM 05-MAR-15 12:00:00 AM
7605 04-MAR-15 07:36:00 PM 04-MAR-15 12:00:00 AM
9631 03-MAR-15 02:20:00 PM 03-MAR-15 12:00:00 AM
READING_TIME是与AMT对应的日期。这是我们系统中的实际数据。 DATE仅仅是过去十天,今天是最重要的。在过去的3天里,我没有相应的记录,因此AMT列为NULL。请记住,这可能发生在实际上任何地方的数据集中间。
如果AMT为NULL,我希望它使用小于记录的DATE值的MAX(READING_TIME)的AMT。以下是我到目前为止所使用的内容:
SELECT
(SELECT AMOUNT
FROM HISTORY
WHERE ID = A.ID
AND (CODE IS NOT NULL AND CODE <> -1)
AND TO_DATE(NVL(READING_DATE, TO_CHAR(TRANSACTION_DATE, 'YYYYMMDD'))
|| ' '
|| NVL(READING_TIME, TO_CHAR(TRANSACTION_DATE, 'HH24MI')), 'YYYYMMDD HH24MI') = A.READING_TIME
) AS AMOUNT,
A.READING_TIME,
A."DATE"
FROM
(SELECT 329 AS ID,
(SELECT MAX(TO_DATE(NVL(READING_DATE, TO_CHAR(TRANSACTION_DATE, 'YYYYMMDD'))
|| ' '
|| NVL(READING_TIME, TO_CHAR(TRANSACTION_DATE, 'HH24MI')), 'YYYYMMDD HH24MI')) AS READING_DATE
FROM HISTORY TH
WHERE TH.ID = 329
AND (TH.CODE IS NOT NULL AND TH.CODE <> -1)
AND TRUNC(TO_DATE(NVL(TH.READING_DATE, TO_CHAR(TRANSACTION_DATE, 'YYYYMMDD'))
|| ' ' || NVL(TH.READING_TIME, TO_CHAR(TRANSACTION_DATE, 'HH24MI')), 'YYYYMMDD HH24MI')) = DATES."DATE"
) AS READING_TIME,
DATES."DATE"
FROM
(SELECT TRUNC(SYSDATE) + 1 - LEVEL AS "DATE"
FROM DUAL
CONNECT BY LEVEL <= 10
) DATES
) A
仅供参考,系统中的这些日期作为字符串开始,因此转换。还有一些有趣的警告,有些是NULL,所以我们使用TRANSACTION_DATE,如果是这样的话。 HISTORY表每天有多条记录。我们正在抓住特定日子的最新记录。
我的最终数据集应如下所示:
AMT READING_TIME DATE
-----------------------------------------------------
24545 09-MAR-15 10:54:00 AM 12-MAR-15 12:00:00 AM
24545 09-MAR-15 10:54:00 AM 11-MAR-15 12:00:00 AM
24545 09-MAR-15 10:54:00 AM 10-MAR-15 12:00:00 AM
24545 09-MAR-15 10:54:00 AM 09-MAR-15 12:00:00 AM
24549 08-MAR-15 09:51:00 PM 08-MAR-15 12:00:00 AM
24549 07-MAR-15 11:37:00 PM 07-MAR-15 12:00:00 AM
24549 06-MAR-15 10:08:00 PM 06-MAR-15 12:00:00 AM
24556 05-MAR-15 11:35:00 PM 05-MAR-15 12:00:00 AM
7605 04-MAR-15 07:36:00 PM 04-MAR-15 12:00:00 AM
9631 03-MAR-15 02:20:00 PM 03-MAR-15 12:00:00 AM
更新:这是方案的SQLFiddle
答案 0 :(得分:0)
您可以使用FIRST_VALUE执行此操作。但首先,我认为你的原始查询 可以简化。
with dates(date_) as (
select trunc(sysdate) + 1 - level
from dual
connect by level <= 10
)
select
h.id,
d.date_,
max(amount) keep (dense_rank first order by coalesce(to_date(h.reading_date || h.reading_time,'yyyymmddhh24mi'), h.transaction_date) desc) amt,
max(coalesce(to_date(h.reading_date || h.reading_time,'yyyymmddhh24mi'), h.transaction_date)) reading_time
from dates d
left outer join history h
on d.date_ = coalesce(to_date(h.reading_date,'yyyymmdd'),trunc(h.transaction_date))
and h.id = 329
and h.code <> -1 and h.code is not null
group by h.id, d.date_;
您可以在一次扫描中完成两次扫描,而不是扫描表格。
完成后,应用FIRST_VALUE函数。
with dates(date_) as (
select trunc(sysdate) + 1 - level
from dual
connect by level <= 10
)
select
first_value(amt) ignore nulls over (order by date_ desc rows between current row and unbounded following) amt,
first_value(reading_time) ignore nulls over (order by date_ desc rows between current row and unbounded following) reading_time,
date_
from (
select
h.id,
d.date_,
max(amount) keep (dense_rank first order by coalesce(to_date(h.reading_date || h.reading_time,'yyyymmddhh24mi'), h.transaction_date) desc) amt,
max(coalesce(to_date(h.reading_date || h.reading_time,'yyyymmddhh24mi'), h.transaction_date)) reading_time
from dates d
left outer join history h
on d.date_ = coalesce(to_date(h.reading_date,'yyyymmdd'),trunc(h.transaction_date))
and h.id = 329
and h.code <> -1 and h.code is not null
group by h.id, d.date_
)
order by date_ desc;
示例:
SQL> select * from myt order by date_ desc;
AMT READING_TIME DATE_
---------- -------------------------- --------------------------
12-MAR-2015 00:00:00
11-MAR-2015 00:00:00
10-MAR-2015 00:00:00
24545 09-MAR-2015 10:54:00 09-MAR-2015 00:00:00
24549 08-MAR-2015 21:51:00 08-MAR-2015 00:00:00
24549 07-MAR-2015 23:37:00 07-MAR-2015 00:00:00
06-MAR-2015 00:00:00
24556 05-MAR-2015 23:35:00 05-MAR-2015 00:00:00
7605 04-MAR-2015 19:36:00 04-MAR-2015 00:00:00
9631 03-MAR-2015 14:20:00 03-MAR-2015 00:00:00
10 rows selected.
SQL> select
first_value(amt) ignore nulls over (order by date_ desc rows between current row and unbounded following) amt,
first_value(reading_time) ignore nulls over (order by date_ desc rows between current row and unbounded following) reading_time,
date_
from myt order by date_ desc;
2 3 4 5
AMT READING_TIME DATE_
---------- -------------------------- --------------------------
24545 09-MAR-2015 10:54:00 12-MAR-2015 00:00:00
24545 09-MAR-2015 10:54:00 11-MAR-2015 00:00:00
24545 09-MAR-2015 10:54:00 10-MAR-2015 00:00:00
24545 09-MAR-2015 10:54:00 09-MAR-2015 00:00:00
24549 08-MAR-2015 21:51:00 08-MAR-2015 00:00:00
24549 07-MAR-2015 23:37:00 07-MAR-2015 00:00:00
24556 05-MAR-2015 23:35:00 06-MAR-2015 00:00:00
24556 05-MAR-2015 23:35:00 05-MAR-2015 00:00:00
7605 04-MAR-2015 19:36:00 04-MAR-2015 00:00:00
9631 03-MAR-2015 14:20:00 03-MAR-2015 00:00:00
10 rows selected.