Skip to content
Advertisement

How can I write a SQL query to calculate the quantity of components sold with their parent assemblies? (Postgres 11/recursive CTE?)

My goal

To calculate the sum of components sold as part of their parent assemblies.

I’m sure this must be a common use case, but I haven’t yet found documentation that leads to the result I’m looking for.

Background

I’m running Postgres 11 on CentOS 7. I have some tables like as follows:

And a view like so, which is mainly to associate the category key with relator.child_name for filtering:

And these tables contain some data like this:

I need to construct a query that, given these data, will return something like the following:

The problem is that I haven’t the first idea how to go about this and in fact it’s getting scarier as I type. I’m having a really hard time visualizing the connections that need to be made, so it’s difficult to get started in a logical way. Usually, Molinaro’s SQL Cookbook has something to get started on, and it does have a section on hierarchical queries, but near as I can tell, none of them serve this particular purpose.

Based on my research on this site, it seems like I probably need to use a recursive CTE /Common Table Expression, as demonstrated in this question/answer, but I’m having considerable difficulty understanding this method and how to use this it for my case.

Aping the example from E. Brandstetter’s answer linked above, I arrive at:

which gets part of the way there:

However, these results include undesired rows (the first two), and when I try to filter the CTE by adding where r.child_category = 'component' to both parts, the query returns no rows:

and when I try to group/aggregate, it gives the following error: ERROR: aggregate functions are not allowed in a recursive query's recursive term

I’m stuck on how to get the undesired rows filtered out and the aggregation happening; clearly I’m failing to comprehend how this recursive CTE works. All guidance is appreciated!

Advertisement

Answer

Basically you have the solution. If you stored the quantities and categories in your CTE as well, you can simply add a WHERE filter and a SUM aggregation afterwards:

My entire query looks like this (which only differs in the details I mentioned above from yours):

demo:db<>fiddle

Note: I didn’t use your view, because I found it more handy to fetch the data from directly from the tables instead of joining data I already have. But that’s just the way I personally like it 🙂

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement