Reputation: 241
Thanks in advance for your replies, this is a 2-part question.
The Database would be called: "Production" The Table would be called: "FruitHistory"
Sample Data:
Is there a way to query this data such that it will only return results that have at least 3 day's worth of data (as an example).
Ex: The query returns Tony's, David's and Aaron's records but not Bern's
Part2:
Building on Part1's rule but now only returning 3 days worth of data at all
Ex: The query returns 11/3-11/5 for Tony and Aaron and all of David's data but still not Bern's.
Thanks!
Upvotes: 0
Views: 73
Reputation:
In Oracle 12.1 or higher, MATCH_RECOGNIZE
can do quick work of such requirements. I create the sample data in a WITH
clause (not part of the SQL statement - use your actual table and column names). I changed the column names - column names should not have spaces in them (your first column does), and they shouldn't be Oracle keywords (like DAY or DATE). I didn't order the output in any way; if this is the final report, not used in further processing, you can add an ORDER BY clause at the end.
with
sample_data(customer, dt, fruit) as (
select 'Tony' , date '2018-11-01', 'Orange' from dual union all
select 'Tony' , date '2018-11-02', 'Apple' from dual union all
select 'Tony' , date '2018-11-03', 'Pear' from dual union all
select 'Tony' , date '2018-11-04', 'Plum' from dual union all
select 'Tony' , date '2018-11-05', 'Grape' from dual union all
select 'David', date '2018-11-03', 'Orange' from dual union all
select 'David', date '2018-11-04', 'Watermelon' from dual union all
select 'David', date '2018-11-05', 'Cantelope' from dual union all
select 'Bern' , date '2018-11-05', 'Kiwi' from dual union all
select 'Aaron', date '2018-11-01', 'Orange' from dual union all
select 'Aaron', date '2018-11-02', 'Apple' from dual union all
select 'Aaron', date '2018-11-03', 'Watermelon' from dual union all
select 'Aaron', date '2018-11-04', 'Kiwi' from dual union all
select 'Aaron', date '2018-11-05', 'Pear' from dual
)
select *
from sample_data
match_recognize (
partition by customer
order by dt desc
all rows per match
pattern ( ^ a{3} )
define a as null is null
)
;
Output:
CUSTOMER DT FRUIT
-------- ---------- -------------
Aaron 2018-11-05 Pear
Aaron 2018-11-04 Kiwi
Aaron 2018-11-03 Watermelon
David 2018-11-05 Cantelope
David 2018-11-04 Watermelon
David 2018-11-03 Orange
Tony 2018-11-05 Grape
Tony 2018-11-04 Plum
Tony 2018-11-03 Pear
Upvotes: 1
Reputation: 86715
Assuming the DBMS you're using is relatively modern it will have analytic / windowed functions. In which case the following should do the type of thing you describe.
SELECT
*
FROM
(
SELECT
*,
COUNT(*) OVER (PARTITION BY customer_name) AS cust_record_count,
ROW_NUMBER() OVER (PARTITION BY customer_name ORDER BY day_column DESC) AS cust_record_id
FROM
yourTable
)
summarised
WHERE
cust_record_count >= 3
AND cust_record_id <= 3
Upvotes: 2
Reputation: 1251
First part:
SELECT Name, Count(*)
FROM table
GROUP BY Name
HAVING Count(*)>2
Second Part:
SELECT *
FROM table
WHERE Name IN (SELECT Name
FROM table
GROUP BY Name
HAVING Count(*)>2)
Upvotes: 0