Reputation: 37
I have been tortured by this issue over the last two weeks and can't spend any more time on it. I would love to hear any ideas from this community, if you have a minute. I'm self taught so I'll have to explain this in lay terms. Thank you for your consideration.
My goal is to fetch all invoices with nonzero balance. This is straightforward enough for regular invoices. The problem arises with payment reminders, because their balance is just the late fee, so in order to fetch their total balance I have to link back to their original invoices through a single field in a connecting table COLLECTIVEINVOICENO
.
Example of table INVOICE
:
invoiceid | invoiceno | invoicetypename | amount
--------------|---------------|---------------------|--------------------
10008 | 123000 | Payment Reminder | 5
10005 | 113000 | Payment Reminder | 5
10001 | 110000 | Invoice | 35
Example of table COLLECTIVEINVOICENO
where 10001
and 10005
are overdue:
invoiceid | followed_up_in (CHAR)
--------------|----------------------------------------------------------
10005 | 113000, 123000
10001 | 113000
I have found a very bad solution, which works to fetch the ledger of a single customer at a time, but it is so demanding of resources there is no way I can use it on the entire table INVOICE
:
select (
select sum(i.amount) as sum
from INVOICE i0
join COLLECTIVEINVOICENO cin0 on cin0.invoiceid = i0.invoiceid
where instr(cin0.followed_up_in, i.invoiceno) > 0
) as original_sum
from INVOICE i
This full table scan is repeated five times in my main select
so as to sort various balances into different columns, and for fetching other data from original invoices besides their balance, such as their locations etc.
My original intention was to left-join the subselect onto INVOICE i
as a view, but there Oracle doesn't recognize i.invoice
in instr(cin0.collectiveinvoiceno, i.invoice)
(ORA-00904: "I"."INVOICENO": invalid identifier).
I am now left to looking into cursors etc., which I am currently doing, but I would really like to know if there are any SQL, non-PL ways about it?
Thank you.
Edit: About splitting the comma-separated data into rows ie. changing the data model to facilitate relations: That would certainly help I'm sure, however the data model is packaged with a third-party software so I can't do anything about it. (I would not be surprised if they do change it at some point though, because it manifests with the end user as a major weakness.)
Edit 2: Have tried splitting the comma-separated data into rows using regexp_substr()
with level
and connect by
and join this view to the main table. I doesn't solve the problem because when I regexp_substr()
is expensive resources-wise when other tables are joined on, and the query doesn't deliver even after half an hour. Google reveals that this is a common problem with regular expressions and one is advised to try stored procedures instead.
I've changed the title to reflect this and I will be grateful on any input on how to solve this using stored procedures. Anyway, thanks!
Upvotes: 1
Views: 204
Reputation: 1933
This may help. It splits the comma delimited followed_up_in
and flattens the resulting list values into rows of invoice numbers using xmltable
before joining with main table.
select i0.invoiceid, sum(i0.amount)
from INVOICE i0
left outer join
( select invoice_id, trim(COLUMN_VALUE) invoiceno
FROM COLLECTIVEINVOICENO,
xmltable(('"' || REPLACE(followed_up_in, ',', '","') || '"'))
) cin0
on cin0.invoiceno = i0.invoiceno
and i0.invoiceid = cin0.invoiceid
group by i0.invoiceid
Upvotes: 1