Reputation: 33
I have a requirement to write a query in Oracle as shown in the screenshots below. Any help is greatly appreciated. Thanks a lot in advance. Vadi.
Table with sample data:
CREATE TABLE fee_check (
trans_date DATE,
fee1 NUMBER(6,3),
fee2 NUMBER(6,3)
);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('18/04/2022','dd/mm/yyyy'), 0.74, 0.87);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('19/04/2022','dd/mm/yyyy'), 0.75, 0.87);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('20/04/2022','dd/mm/yyyy'), 0.75, 0.87);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('21/04/2022','dd/mm/yyyy'), 0.73, 0.87);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('22/04/2022','dd/mm/yyyy'), 0.73, 0.87);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('23/04/2022','dd/mm/yyyy'), 0.73, 0.87);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('24/04/2022','dd/mm/yyyy'), 0.73, 0.87);
INSERT INTO fee_check(trans_date, fee1, fee2) VALUES (to_date('25/04/2022','dd/mm/yyyy'), 0.76, 0.87);
COMMIT;
Upvotes: 0
Views: 67
Reputation: 168671
If you want to only count consecutive rows (rather than aggregating non-consecutive groups with the same fee values together) then, from Oracle 12, you can use MATCH_RECOGNIZE
to do row-by-row processing:
SELECT *
FROM fee_check
MATCH_RECOGNIZE(
ORDER BY trans_date
MEASURES
FIRST(trans_date) AS trans_date,
COUNT(trans_date) AS day_count,
FIRST(fee1) AS fee1,
FIRST(fee2) AS fee2
PATTERN (same_fees+)
DEFINE same_fees AS fee1 = FIRST(fee1) AND fee2 = FIRST(fee2)
)
Or, in earlier versions, you can use analytic functions:
SELECT MIN(trans_date) AS trans_date,
COUNT(*) AS day_count,
MIN(fee1) AS fee1,
MIN(fee2) AS fee2
FROM (
SELECT f.*,
ROW_NUMBER() OVER (ORDER BY trans_date) -
ROW_NUMBER() OVER (PARTITION BY fee1, fee2 ORDER BY trans_date) AS grp
FROM fee_check f
)
GROUP BY grp
Which, for the sample data:
CREATE TABLE fee_check (trans_date, fee1, fee2) AS
SELECT DATE '2022-04-18', 0.74, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-19', 0.75, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-20', 0.75, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-21', 0.73, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-22', 0.73, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-23', 0.73, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-24', 0.73, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-25', 0.76, 0.87 FROM DUAL UNION ALL
SELECT DATE '2022-04-26', 0.75, 0.87 FROM DUAL;
Note: there is an extra row added at the end that has the same fee1
and fee2
values earlier in the data set.
Both output:
TRANS_DATE DAY_COUNT FEE1 FEE2 2022-04-18 00:00:00 1 .74 .87 2022-04-19 00:00:00 2 .75 .87 2022-04-21 00:00:00 4 .73 .87 2022-04-25 00:00:00 1 .76 .87 2022-04-26 00:00:00 1 .75 .87
db<>fiddle here
Upvotes: 1
Reputation: 92
This is the solution of your problem
SELECT MIN(trans_date) trans_date, COUNT(*) DayCount, fee1, fee2
FROM fee_check
GROUP BY fee1,fee2
ORDER BY trans_date
Upvotes: 1