In situations where the requirements are not met for a materialized view, the following two options exist:
1) You can create a cross-reference table and save this update using triggers.
The concepts will be the same with Oracle, but at the moment I just have SQL Server installed to run the test, see this setting:
create table MAIL ( ID INT IDENTITY(1,1), [FROM] VARCHAR(200), SENT_DATE DATE, CONSTRAINT PK_MAIL PRIMARY KEY (ID) ); create table MAIL_TO ( ID INT IDENTITY(1,1), MAIL_ID INT, [NAME] VARCHAR (200), CONSTRAINT PK_MAIL_TO PRIMARY KEY (ID) ); ALTER TABLE [dbo].[MAIL_TO] WITH CHECK ADD CONSTRAINT [FK_MAILTO_MAIL] FOREIGN KEY([MAIL_ID]) REFERENCES [dbo].[MAIL] ([ID]) GO ALTER TABLE [dbo].[MAIL_TO] CHECK CONSTRAINT [FK_MAILTO_MAIL] GO CREATE TABLE CompositeIndex_MailSentDate_MailToName ( [MAIL_ID] INT, [MAILTO_ID] INT, SENT_DATE DATE, MAILTO_NAME VARCHAR(200), CONSTRAINT PK_CompositeIndex_MailSentDate_MailToName PRIMARY KEY (MAILTO_ID,MAIL_ID) ) GO CREATE NONCLUSTERED INDEX IX_MailSent_MailTo ON dbo.CompositeIndex_MailSentDate_MailToName (SENT_DATE,MAILTO_NAME) CREATE NONCLUSTERED INDEX IX_MailTo_MailSent ON dbo.CompositeIndex_MailSentDate_MailToName (MAILTO_NAME,SENT_DATE) GO CREATE TRIGGER dbo.trg_MAILTO_Insert ON dbo.MAIL_TO AFTER INSERT AS BEGIN INSERT INTO dbo.CompositeIndex_MailSentDate_MailToName ( MAIL_ID, MAILTO_ID, SENT_DATE, MAILTO_NAME ) SELECT mailTo.MAIL_ID,mailTo.ID,m.SENT_DATE,mailTo.NAME FROM inserted mailTo INNER JOIN dbo.MAIL m ON m.ID = mailTo.MAIL_ID END GO CREATE TRIGGER dbo.trg_MAILTO_Delete ON dbo.MAIL_TO AFTER DELETE AS BEGIN DELETE mailToDelete FROM dbo.MAIL_TO mailToDelete INNER JOIN deleted ON mailToDelete.ID = deleted.ID END GO CREATE TRIGGER dbo.trg_MAILTO_Update ON dbo.MAIL_TO AFTER UPDATE AS BEGIN UPDATE compositeIndex SET compositeIndex.MAILTO_NAME = updates.NAME FROM dbo.CompositeIndex_MailSentDate_MailToName compositeIndex INNER JOIN inserted updates ON updates.ID = compositeIndex.MAILTO_ID END GO CREATE TRIGGER dbo.trg_MAIL_Update ON dbo.MAIL AFTER UPDATE AS BEGIN UPDATE compositeIndex SET compositeIndex.SENT_DATE = updates.SENT_DATE FROM dbo.CompositeIndex_MailSentDate_MailToName compositeIndex INNER JOIN inserted updates ON updates.ID = compositeIndex.MAIL_ID END GO INSERT INTO dbo.MAIL ( [FROM], SENT_DATE ) SELECT 'SenderA','2018-10-01' UNION ALL SELECT 'SenderA','2018-10-02' INSERT INTO dbo.MAIL_TO ( MAIL_ID, NAME ) SELECT 1,'CustomerA' UNION ALL SELECT 1,'CustomerB' UNION ALL SELECT 2,'CustomerC' UNION ALL SELECT 2,'CustomerD' UNION ALL SELECT 2,'CustomerE' SELECT * FROM dbo.MAIL SELECT * FROM dbo.MAIL_TO SELECT * FROM dbo.CompositeIndex_MailSentDate_MailToName
Then you can use the dbo.CompositeIndex_MailSentDate_MailToName table for JOIN for the rest of your data. This is useful in environments where the speed of attachments and updates is low, but your requests are high. Therefore, the relative overhead during the implementation of the triggers is small.
The advantage of this is that it is updated in real time.
2) If you do not want overhead for performance / trigger management, and you only need it for next day reports, you can create a view and a night process that cuts the table and selects the whole view in a materialized table,
I have successfully used this to index flattened relational data that requires joining across a dozen or so tables. Reduce response time from hours to a few seconds. Although this is a costly request, you can set the task to run without hours if you have periods of reduced usage.