Question

I have one table of tickets containing three relevant columns: id, start and finish where start and finish are timestamps.

I have a second table (intervals) with only one relevant column which is time point. time_point is also a timestamp. time_point is always every 15 minutes. That is content of this second table is:

8:00
8:15
8:30
...

The first table (ticket) has 4 millions of records. The second has only 96 records (24 * 4).

I have to select how many tickets are open at any time_point

I wrote the following query: (simplified version)

select * 
from interval, ticket 
where (finish is null or finish > time_point)
      and start < time_point

which works but it is too slow. The problem is that there is no real join between both tables and a I presume that a full table scan is performed for every row.

How can I get better performance here?

Thanks!

EDIT: This is an Oracle DB.

Was it helpful?

Solution

i believe you dont need to cross join or create an interval table. Instead try following:

> select count(*), tsd from (
>         select 
>         /****************************************************************
>         Now 
>         1- bring your finish column into the format you need: HH24:MI
>         2- truncate its content down to the interval the row belongs to
>         ****************************************************************/
>         to_char(dt,'HH24')|| decode(trunc(to_char(dt,'MI')/15) * 15,0,'00',trunc(to_char(dt,'MI')/15)*15)
> tsd
>         from (
>             select  nvl( finish  ,to_date('31.12.2999', 'dd.mm.yyyy'))   dt      -- 
>               from tickets 
>               /****************************************************************
>               Now Filter out your tickets(before truncate), to find the relevant 
>               tickets for your period use a Parameter date and compare it to the
>               start and end columns nvl( finish  ,to_date('31.12.2999', dd.mm.yyyy'))
>               ****************************************************************/
>               where P_YOUR_PARAM_DATE between start 
>                                       and nvl( finish  ,to_date('31.12.2999', 'dd.mm.yyyy'))
>             ) dat  
>      )  group by tsd order by tsd ;

OTHER TIPS

One way to speed this up is to include the finish column in a composite index so there's no need to read from the table to fetch that value:

                create index IX_Tickets on Tickets(start,finish)

P.S. Drop any simple index on Tickets.start as well.

P.P.S. Please clarify: 8:00, 8:15 in your intervals table are not timestamp data type. Did you elminate the date element in your question for the sake of simplicity?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top