SQLite - Help optimizing aggregate total of previous rows with multiple conditions

瘦欲@ 提交于 2019-12-06 13:16:55
whytheq

Please refer to suggestions HERE ON SO for ways you can speed things up.

Two or three SO heavyweights have contributed so I'd get in touch with your DBA and see what changes can be made.

Seems the consensus is that you need to add some indexing on the changes table.

I also likes the idea of adding a couple of calculated fields into this table to then make the subsequent script a lot more readable.

If you are able to change some of the data types then there's lots of suggestions in the answers.

JPBro

First of all - thanks to whytheq and the contributors in the following thread: Can this be simplified and therefore optimized which is worth a read even though the solutions are not all applicable to SQLite due to its limitations. I was able to implement some optimizations based on the suggestions to cut the SELECT time in half.

How it was done:

  1. Added and EffectiveDate column that stores the date portion of the ApprovedDate when Approved=TRUE, or IssuedDate when Approved=FALSE as an integer instead of as ISO8601 text.

  2. Added a new column called EffectiveID that stores the Category, Approved, zero-padded EffectiveDate and zero-padded DocumentNumber as a single value for quicker comparisons.

  3. Created an UPDATE TRIGGER on update of the Approved, IssuedDate and ApprovedDate columns to update the EffectiveDate column.

  4. Created a UPDATE TRIGGER on the EFfectiveDate, Category, Approved, and Number columns to update the EffectiveID field accordingly.

  5. Created a TRIGGER on insert of a new row to update the EffectiveDate accordingly.

  6. Added INDEXes for the EffectiveDate and EffectiveID columns

  7. Rearranged the ON clause tests to reduce the number of matches, reducing processing

  8. Changed the JOIN to select only the required subset of columns in the result set.

The final SQL is as follows:

SELECT 
a.GUID, 
TOTAL(CASE WHEN b.Value>0 THEN b.Value ELSE 0 END) as positive_previous_total, 
TOTAL(CASE WHEN b.Value<0 THEN b.Value ELSE 0 END) as negative_previous_total 
FROM 
Changes AS a 
LEFT JOIN 
(SELECT rowid, Value, Category, Approved, EffectiveId FROM Changes) as b 
ON 
b.EffectiveID < a.EffectiveID 
AND b.Category=a.Category
AND b.Approved=a.Approved
AND b.rowid != a.rowid
GROUP BY 
a.rowid
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!