0

I am sorry in advance, I tried researching it but can't seem to find something that fits.

Following i have found already, but can not use for my issue:

Filtering MySQL query result set to yield multiple occurences within a specific period of time

SQL Query To Obtain Value that Occurs more than once

I was not able to modify these statements to solve my issue.

I would like to select all occurances of a Data which occurs five times or more in a Table within 24 hours. The table contains data about the past years.

The Table is not sorted by Date (Timestamp dd.mm.yy hh:mm:ss,sssssssss)

This shows me the overall occurance >= 5, but not if this happened within 24 hours.

SELECT Column, COUNT(*) FROM Table
GROUP BY Column
HAVING COUNT(*) >= 5;

Any suggestions for search keywords are welcome.

Thank you in advanced. Best regard Denyo

EDIT: Thank you all for your help and im sorry for the bad asked question. Ill try to answer all your questions.

@mathguy The Database version is 12c.

It does have one column for "data" and another column for date (timestamp). I would like to find occurrences of the same value in the "data" column within a <=24 hour window from 1st occurence of this value.

@Matthew McPeak Im still trying to understand your SQL Statement. Sry im totally new with SQL. This ist obvious by the way i asked my question :(.

@Aurelian My question is not well asked. So your answer couldn't fit, im sorry.

@all I feel bad about my bad asked question and wasting your time.

I hope you'll accept my apology.

Best regards Denyo

EDIT2: Im trying this now

begin
for i in (select Table.DATE(Timestamp), Table.IP, Table.Value from Table) 
loop
  dbms_output.put_line(i.Value); (instead of this output, i would like to add another loop and compare the Date(Timestamp) with i.DATE and count if matches
end loop;
end;
Denyo
  • 115
  • 1
  • 13
  • 1
    What does your table look like? Does it have one column for "data" and another column for date/time (in Oracle, that is data type `date` or perhaps `timestamp`)? And you need to find occurrences of the same value in the "data" column within a 24 hour window? If so, here are a few more questions. Does "within 24 hours" mean <= 24 hours, or < 24 hours? Also, if you have 200 occurrences, one hour apart, do you want to show (first through 24th or 25th) and then the next one following, or do you want to show OVERLAPPING: 1 through 24, but also 2 through 25, 3 through 26, etc.? –  Apr 06 '18 at 16:53
  • 1
    And: What VERSION of Oracle are you using? SELECT * FROM V$VERSION will tell you if you don't know. –  Apr 06 '18 at 16:53
  • Hi mathguy, thx for your help. i ve updated my question. – Denyo Apr 09 '18 at 11:02
  • You only want the number of occurrences within 24 hours of the _first_ occurrence? So, if you have 1 occurrence for a value of "data" on Tuesday and then 20 occurrences on Friday, you want to see "1" for that value of "data", and not 20? – Matthew McPeak Apr 09 '18 at 11:06
  • Hi, i want to see the value when it occures more then 5 times within 24h houer aftr his 1st occurence. Example: it occurs now once. Next 4 ocurences are in three days (from now), followed by 1 occurence in 10 days (from now). The result of my sql-statement wont show anything. – Denyo Apr 09 '18 at 11:11
  • Other example: A value occures now followed by 4 in 10 hours (from now). The sql-statement would show this value. I hope it is understandable. The lack of sql knowledge by me makes it hard for me to think in SQL and ask proper questions (providing the neccassary information) :(. – Denyo Apr 09 '18 at 11:12
  • In other programming language, i would collect the existing values loop through the whole list of values by searching for other occurences of this value within 24 hours relative to the selected one (loop in loop). Now im searching for a ability to loop through the rows of the the value column and comparing the corresponding date column. Hope this is the right way. – Denyo Apr 09 '18 at 11:18

4 Answers4

1

I would like to find occurrences of the same value in the "data" column within a <=24 hour window from 1st occurence of this value.

The first occurrence per value:

select value, min(timestmp) from mytable group by value;

Now we must check whether there are at least four more occurences of a value after its first occurrence:

select value, min(timestmp)
from mytable m
group by value
having
(
  select count(*)
  from mytable following24hours
  where following24hours.value = m.value
    and following24hours.timestmp > min(m.timestmp) 
    and following24hours.timestmp < min(m.timestmp) + interval '24' hour
) >= 4;
Thorsten Kettner
  • 89,309
  • 7
  • 49
  • 73
  • This is the statement i am searching for. Thank you and all others who helped. Im glad that a loop is not neccassary. – Denyo Apr 09 '18 at 13:01
  • Looping is exactly what this solution does, you just don't see it - it's hidden behind the SQL code. I posted a solution using the MATCH_RECOGNIZE clause (available in Oracle 12.1 and later) which should be much more efficient than this solution; but only you can decide that, running the solutions on your actual data. –  Apr 09 '18 at 14:38
  • I ve tried the MATCH_RECOGNIZE solution by mathguy too. It solved my problem too. Thank you for that solution mathguy. – Denyo Apr 10 '18 at 11:45
1

In Oracle 12, you can use the MATCH_RECOGNIZE clause for a very clean and efficient solution. (You can test it against the accepted answer, to verify if it is correct and to see which is more efficient on your actual data).

select value, first_timestmp
from   mytable
match_recognize(
  partition by value
  order by     timestmp
  measures     a.timestmp as first_timestmp
  one row per match
  pattern      ( a b{4,} )
  define       b as b.timestmp <= a.timestmp + interval '24' hour
)
;
  • Hey mathguy, this solution does solve my problem too. My table has only 2k rows (still growing). At the moment, i can not see any differences in speed (efficiency). Now i must understand with the help of google and documentation, how both solutions are working. Thank you very much for your help. – Denyo Apr 10 '18 at 11:23
0

You can use the following code:

SELECT DISTINCT Column, COUNT(*) 
FROM TABLE
WHERE date >= SYSDATE - 1
GROUP BY Column
HAVING COUNT(*) >= 5;   
Aura
  • 1,283
  • 2
  • 16
  • 30
  • Oh... We are interpreting "within 24 hours" differently. Perhaps you are right (within "the past 24 hours"). I understood it to mean "within 24 hours between the first and the last" (could have been eight months ago). –  Apr 06 '18 at 16:55
  • I am assuming they need "within 24 hours" from the above mentioned query. I hope it works and fulfills the requirement. – Aura Apr 06 '18 at 16:58
  • 1
    "Within 24 hours" doesn't mean within **the last** 24 hours (measured from "now") - if you must finish something in one hour from when you start, it must be "completed within one hour." But for non-native English speakers, it **may** mean what you assumed. –  Apr 06 '18 at 17:05
  • I agree, once the question is updated I will modify my answer accordingly. – Aura Apr 06 '18 at 17:26
0

You can use this expression to count up the occurrences for each value in the previous 24 hours:

 COUNT(*) OVER (PARTITION BY column
                ORDER BY date_column 
                RANGE NUMTODSINTERVAL(24,'HOUR') PRECEDING

Then, get the rows where that expression is at least 5.

I don't have your data, but here is an example that uses DBA_OBJECTS. This version will show any object updates where the object OWNER has updated 5 or more objects in the prior five-day period.

with five_day_count as 
( select o.owner, 
  last_ddl_time,
  count(*) over ( partition by owner 
                  order by last_ddl_time 
                  range numtodsinterval(5, 'DAY') PRECEDING ) cnt
  from dba_objects o)
SELECT owner, last_ddl_time, cnt 
FROM five_day_count
WHERE cnt >= 5

... and, just for fun, this query will give one row for each OWNER -- the five-day interval with the most updated objects for that user. A variant of this version may be more applicable to your need.

with five_day_count as 
( select o.owner, 
         last_ddl_time range_end,
         min(last_ddl_time) 
            over ( partition by owner 
                   order by last_ddl_time 
                   range numtodsinterval(5, 'DAY') PRECEDING ) range_start,
         count(*) 
            over ( partition by owner 
                   order by last_ddl_time range 
                   numtodsinterval(5, 'DAY') PRECEDING ) cnt
  from dba_objects o),
max_counts as 
( SELECT owner, 
         range_start, 
         range_end, 
         cnt, 
         row_number() 
             over ( partition by owner 
                    order by cnt desc, 
                             range_end desc) rn 
  FROM five_day_count
  WHERE cnt > = 5)
select owner, range_start, range_end, cnt
from max_counts
where rn = 1;
Matthew McPeak
  • 17,705
  • 2
  • 27
  • 59