Django ORM equivalent of SQL Sum - sql

I have a django model as follows:
class Order(models.Model):
cash=models.DecimalField(max_digits=11,decimal_places=2,default=0)
balance=models.DecimalField(max_digits=11,decimal_places=2,default=0)
current_ac=models.DecimalField(max_digits=11,decimal_places=2,default=0)
added_by = models.ForeignKey(User)
There can be multiple Orders and multiple users can create orders.
How can I get the sum of all orders for each columns for a particular user using Django queries, an SQL equivalent would be something like
Select sum(cash), sum (balance), sum(current_ac) from Orders where added_by = 1

You can get your expected result from the code below
from django.db.models import Sum
result = Order.objects.filter(added_by_id=1).aggregate(total_cash=Sum('cash'), total_balance =Sum('balance'), total_current_ac=Sum('current_ac'))
and it will give you a dictionary like this:
{'total_cash': Decimal('110.00'), 'total_balance': Decimal('110.00'), 'total_current_ac': Decimal('110.00')}

Related

Using aggregation on subquery in Django ORM

I have a table like this
Category
Subcategory
Sub_subcategory
Cat_1
Subcat_1
Sub_subcat_1
Cat_1
Subcat_1
Sub_subcat_2
Cat_1
Subcat_2
Sub_subcat_3
Cat_2
Subcat_2
Sub_subcat_4
Cat_3
Subcat_3
Sub_subcat_5
And I need to find in how many categories each subcategory appears.
So my expected output based on above table would be:
Subcategory
Total
Subcat_2
2
Subcat_1
1
Subcat_3
1
So I can get that by running following SQL query:
SELECT subcategory, count(*) total FROM (
SELECT DISTINCT subcategory, category FROM table_1
) as temp_table GROUP BY subcategory ORDER BY total DESC
I spent a lot of time trying to get the same result with Django ORM but wasn't able to get it done.
I expected this code to work:
subquery = Table1.objects.values('subcategory', 'category').distinct()
results = subquery.annotate(total=Count('*')).values('subcategory', 'total').order_by('-total')
But it works exactly the same as without 'distinct()' in subquery, so it counts all categories for every subcategory.
I also tried to find similar case in other questions, but those with subqueries usually relate to JOINing tables and using OuterRef, here it is more like getting results based on temporary table that is created by subquery.
Does anyone know how can I achieve that (or if it's even possible)?
this should do the job
dictionary = {}
queryset = YOUR_queryset_with_table_HERE.objects.all()
for i in queryset:
subcategory = i.subcategory
#check if subcategory already in dictionary
#if not create it with 1, else +=1
if dictionary["subcategory"]:
dictionary["subcategory"] += 1
else:
dictionary["subcategory"] = 1
print(dictionary)
Say you have two models in a many-to-many relationship similar to this:
class Category(models.Model):
category_name = models.CharField(max_length=30)
class SubCategory(models.Model):
subcategory_name = models.CharField(max_length=30)
category = models.ManyToManyField(Category)
Then this should give you the total number of categories in which each subcategory appears:
results = SubCategory.objects.all().annotate(total=Count('category')).values('subcategory_name', 'total')

multiplie outputs with different wheres

What do I have to change to get different results from different names.The table should give me the debts of each of them, this is calculated by the amount and the price of the drink. Now it should show all the names with the corresponding invoice that happens after the select
%sql select name, sum(getraenk.preis*schulden.menge) schulden from schulden \
join person on (fk_person = person.id)\
join getraenk on (fk_getraenk = getraenk.id)\
where name like ("dani")
Edit: it should spend all the names with their debts, that is:
dani = 8.5
michael = 12.5
...
Just in case your problem is very simple, you should be able to see all names and values with an SQL that looks like this:
select name, getraenk.preis*schulden.menge schulden
from schulden
join person on (fk_person = person.id)
join getraenk on (fk_getraenk = getraenk.id)
Note that I removed the where clause... this was the part that limited it to one name.
You also don't need the sum clause here unless you are doing a group by
Have you considered simply using GROUP BY name at the end of this query?
https://www.w3schools.com/sql/sql_groupby.asp
This will give you the sum of total debt for all names in your table which sounds like the result you are looking for.
You're missing
GROUP BY name
in the query.

Rails 3 Sum Product of two fields

I need to calculate the sum of the product of two fields in my Rails 3 app (i.e. the equivalent to Excel's sumproduct function). Is there a method in Rails that will help with this and if not, then what would be the rails code using custom sql?
For example, a Hotel has many Rooms. A Room has attributes of sqft (square feet), quantity (of that size) and hotel_id. I would like to calculate the total sqft of all the Rooms in a given Hotel. In SQL, for a Hotel.id = 8, I believe the following statement will work:
select sum(rooms.sqft * rooms.quantity) as SumSqft from rooms inner join hotels on rooms.hotel_id = hotels.id where hotels.id = 8;
Yep :
Room.where(hotel_id: 8).sum("sqft * quantity")
def calculate
#hotel=Hotel.find(params[:id]
#rooms=Room.all.where(:hotel_id=>#hotel.id)
sum=0
#rooms.each do |room|
sum=sum+room.sqft*room.quantity
end
return sum
end

NHibernate Return Values

I am currently working on a project using NHiberate as the DAL with .NET 2.0 and NHibernate 2.2.
Today I came to a point where I had to join a bunch of entities/collections to get what I want. That is fine.
What got me was that I do not want the query to return a list of objects of a certain entity type but rather the result would include various properties from different entities.
The following query is not what I am doing but it is kind of query that I am talking about here.
select order.id, sum(price.amount), count(item)
from Order as order
join order.lineItems as item
join item.product as product,
Catalog as catalog
join catalog.prices as price
where order.paid = false
and order.customer = :customer
and price.product = product
and catalog.effectiveDate < sysdate
and catalog.effectiveDate >= all (
select cat.effectiveDate
from Catalog as cat
where cat.effectiveDate < sysdate
)
group by order
having sum(price.amount) > :minAmount
order by sum(price.amount) desc
My question is, in this case what type result is supposed to be returned? It is certainly not of type Order, neither is of type LineItems.
Thanks for your help!
John
you can always use List of object[] for returning data and it will work fine.
This is called a projection, and it happens any time you specify an explicit select clause that contains rows from various tables (or even aggregate / summary data from a single table).
Using LINQ you can create anonymous objects to store these rows of data, like this:
var crunchies = (from foo in bar
where foo.baz == quux
select new { foo.corge, foo.grault }).ToList();
Then you can do crunchies[0].corge for example to pull out the rows & columns.
If you are using NHibernate.Linq this will "just work".
If you're using HQL or Criteria API, then what Fahad mentioned will work. You'll get a List<object[]> as a result, and the index of the array references the order of the columns that you returned in your select clause.

SUM(a*b) not working

I have a PHP page running in postgres. I have 3 tables - workorders, wo_parts and part2vendor. I am trying to multiply 2 table column row datas together, ie wo_parts has a field called qty and part2vendor has a field called cost. These 2 are joined by wo_parts.pn and part2vendor.pn. I have created a query like this:
$scoreCostQuery = "SELECT SUM(part2vendor.cost*wo_parts.qty) as total_score
FROM part2vendor
INNER JOIN wo_parts
ON (wo_parts.pn=part2vendor.pn)
WHERE workorder=$workorder";
But if I add the costs of the parts multiplied by the qauntities supplied, it adds to a different number than what the script is doing. Help....I am new to this but if someone can show me in SQL I can modify it for postgres. Thanks
Without seeing example data, there's no way for us to know why you're query totals are coming out differently that when you do the math by hand. It could be a bad join, so you are getting more/less records than you expected. It's also possible that your calculations are off. Pick an example with the smallest number of associated records & compare.
My suggestion is to add a GROUP BY to the query:
SELECT SUM(p.cost * wp.qty) as total_score
FROM part2vendor p
JOIN wo_parts wp ON wp.pn = p.pn
WHERE workorder = $workorder
GROUP BY workorder
FYI: MySQL was designed to allow flexibility in the GROUP BY, while no other db I've used does - it's a source of numerous questions on SO "why does this work in MySQL when it doesn't work on db x...".
To Check that your Quantities are correct:
SELECT wp.qty,
p.cost
FROM WO_PARTS wp
JOIN PART2VENDOR p ON p.pn = wp.pn
WHERE p.workorder = $workorder
Check that the numbers are correct for a given order.
You could try a sub-query instead.
(Note, I don't have a Postgres installation to test this on so consider this more like pseudo code than a working example... It does work in MySQL tho)
SELECT
SUM(p.`score`) AS 'total_score'
FROM part2vendor AS p2v
INNER JOIN (
SELECT pn, cost * qty AS `score`
FROM wo_parts
) AS p
ON p.pn = p2v.pn
WHERE p2n.workorder=$workorder"
In the question, you say the cost column is in part2vendor, but in the query you reference wo_parts.cost. If the wo_parts table has its own cost column, that's the source of the problem.