给定一个包含两列的表格,一个独特的增加ID
和一个Transaction_Date
就是它的样子。我想找到每小时的第一个ID
,包括没有交易的时间。
尝试使用Oracle我有:
WITH parameters AS(
SELECT TO_DATE('01/03/2015','DD/MM/YYYY') AS START_DAY
, TO_DATE('08/03/2015','DD/MM/YYYY') AS END_DAY
FROM DUAL
), hour_range AS(
SELECT START_DAY + (LEVEL-1)/24 AS DT
FROM PARAMETERS
CONNECT BY LEVEL <= (END_DAY - START_DAY + 1)*24
)
SELECT TO_CHAR(HOUR_RANGE.DT,'DD-MON-YYYY HH24:"00"'),
MIN (T.Transaction_ID)
FROM HOUR_RANGE
LEFT JOIN Transactions T ON T.Transaction_Date > DT
GROUP BY TO_CHAR(HOUR_RANGE.DT,'DD-MON-YYYY HH24:"00"')
ORDER BY 1;
这似乎需要花费大量时间才能运行,即使在Transaction_ID
和Transaction_Date
上有索引。
有更好的方法吗?
加
尝试更好的方式 - 仍然需要很长时间:
with parameters as(
select to_date('01/03/2015','dd/mm/yyyy') as start_day
, to_date('08/03/2015','dd/mm/yyyy') as end_day
from dual
), hour_range as(
select start_day + (level-1)/24 as dt
from parameters
connect by level <= (end_day - start_day + 1)*24
), tx as(
select to_char(rt.transaction_date,'dd-mon-yyyy hh24:"00"') tx_time,
min(rt.transaction_id) min_tx_id
from Transactions rt
join hour_range on rt.transaction_date >= hour_range.dt and
rt.transaction_date < hour_range.dt + (1/24)
group by to_char(rt.transaction_date,'dd-mon-yyyy hh24:"00"'))
select to_char(h.dt,'dd-mon-yyyy hh24:"00"'),
t.min_tx_id
from hour_range h
left join tx t on t.tx_time = h.dt
order by 1;
这是基于@DavidAldridge的建议和一些调整(我希望我有正确的),因为我忘了解释日期是TimeStamp
。不知道它是否有效,因为它还没有完成。
答案 0 :(得分:2)
考虑一下:
LEFT JOIN Transactions T ON T.Transaction_Date > DT
每小时记录都会加入到大于它的每个交易记录中。
你想要的是:
LEFT JOIN Transactions T ON T.Transaction_Date >= DT and
T.Transaction_Date < DT + (1/24)
此外,您可以考虑在加入小时列表之前通过trunc(transaction_date,&#39; HH&#39;)汇总交易记录,然后您可以发出qui-join。
类似的东西:
with
parameters as
(select to_date('01/03/2015','dd/mm/yyyy') as start_day,
to_date('08/03/2015','dd/mm/yyyy') as end_day
from dual),
hour_range as
(select start_day + (level-1)/24 as dt
from parameters
connect by level <= (end_day - start_day + 1)*24),
tx as
(select trunc(transaction_date, 'hh') tx_hour,
min(t.transaction_id) min_tx_id
from transactions
join parameters on transaction_date >= start_day and
transaction_date < end_day
group by trunc(transaction_date, 'hh'))
select to_char(hour_range.dt,'dd-mon-yyyy hh24:"00"'),
min_tx_id
from hour_range h
left join tx t on t.transaction_date = h.dt
group by to_char(hour_range.dt,'dd-mon-yyyy hh24:"00"')
order by 1;
答案 1 :(得分:0)
我希望尽早过滤,所以我会在加入生成的小时列表之前完成小组,例如:
WITH parameters AS (SELECT TO_DATE('01/03/2015','DD/MM/YYYY') AS START_DAY,
TO_DATE('08/03/2015','DD/MM/YYYY') AS END_DAY
FROM DUAL),
hour_range AS (SELECT START_DAY + (LEVEL-1)/24 AS DT
FROM PARAMETERS
CONNECT BY LEVEL <= (END_DAY - START_DAY + 1)*24),
results as (select trunc(dt, 'hh24') hr,
min(transaction_id) id
from hour_range
where dt between (select start_day from parameters) and (select end_day from parameters)
group by trunc(dt, 'hh24'))
select to_char(hrg.dt, 'DD-MON-YYYY hh24:mm') dt,
res.id
from hour_range hrg
left outer join results res on (hrg.dt = res.hr);