Convert SQLite to Django ORM - mysql

I have a query in SQLite which groups the fields by weeks and performs sum and average over distance and time fields in the same table:
select
strftime('%W', datetime) WeekNumber,
sum(distance) as TotalDistance,
sum(distance)/sum(time) as AverageSpeed
from sample_login_run
group by WeekNumber;
I am trying to convert this query to Django ORM and avoid using Raw function. I understand that I would need to use extra in Django ORM. That should not be a problem though. I came up this:
Run.objects.extra(select={'week': "strftime('%%W', datetime)"}).values(
'week','distance').annotate(
total_distance=Sum('distance'), average_time=F('distance') / F('time'))
But this is also grouping the data by average_time and average_distance field. Any help will be really appreciated. Thank you.

Right solution for this is:
Run.objects.extra(select={'week': "cast(strftime('%%W', date_run) as integer)"}).values('week').annotate(
total_distance=Sum('distance'), average_time=F('distance') / F('time'))
Fields passed in values will go under group by part of the query.

Related

Select a sum in Knex.js without using .raw

I am trying to rewrite some MySQL queries in Knex.js, and I feel like I'm running into .raw at every turn, which feels counter to the reason I want to use Knex in the first place.
Is it possible to write the following query without using .raw?
SELECT
product,
SUM(revenue)
FROM orders
Using raw, it works to write:
knex()
.select(
'product',
knex.raw('SUM(revenue)')
)
.from('orders')
but the idea of using Knex was to avoid using MySQL query strings, so I'm hoping there's another way. Or does everyone just use .raw everywhere, and I'm misunderstanding something? Very possible, I'm new to this.
You can use the sum method.
sum — .sum(column|columns|raw) Retrieve the sum of the values of a
given column or array of columns (note that some drivers do not
support multiple columns). Also accepts raw expressions.
knex('users').sum('products')
Outputs:
select sum("products") from "users"
Probably be something like this:
knex()
.select('product')
.sum('revenue')
.from('orders')
You should adjust to your specific case. You might need to use something like groupBy('product') to get total revenue per product.
You should really go over knex's documentation, it's pretty good and straight forward and you definitely should not be using raw all the time.
You can even specify the returning sum column name like this:
knex(tableName)
.select('product')
.sum({ total: 'revenue' })
.groupBy('product');

Knex.js Select Average and Round

I am switching an application from PHP/MYSQL to Express and am using knex to connect to the MYSQL database. In one of my queries I use a statement like such (I have shortened it for brevity.)
SELECT ROUND(AVG(Q1),2) AS Q1 FROM reviews WHERE id=? AND active='1'
I am able to use ROUND if I use knex.raw but I am wondering if there is a way to write this using query builder. Using query builder makes dealing with the output on the view side so much easier than trying to navigate the objects returned from the raw query.
Here is what I have so far in knex.
let id = req.params.id;
knex('reviews')
//Can you wrap a ROUND around the average? Or do a Round at all?
.avg('Q1 as Q1')
.where('id', '=', id)
Thanks so much!
You can use raw inside select. In this case:
knex('reviews')
.select(knex.raw('ROUND(AVG(Q1),2) AS Q1'))
Check the docs here for more examples and good practices when dealing with raw statements.

Access query amazing

When I do that on access, SELECT RMonturesImp.N°Fac
FROM RMonturesImp, Rpartielun
WHERE NOT (RMonturesImp.N°Fac IN (1,2,5))
GROUP BY RMonturesImp.N°Fac;
but when I do this
SELECT RMonturesImp.N°Fac
FROM RMonturesImp, Rpartielun
WHERE NOT (RMonturesImp.N°Fac IN Requête2)
GROUP BY RMonturesImp.N°Fac;
it doesn't work (it shows 1,2,5 indeed) although the result of Requête2 (which is a query) is also (1,2,5). I can't understand this!
Thanks in advance
It's quite easy. The IN (1,2,5)) must be explicit as SQL will not evaluate an expression not to say a function to obtain the values for IN.
So build your SQL in code creating the string, or pull the values from a (temp) table.
Try this:
SELECT RMonturesImp.N°Fac
FROM RMonturesImp, Rpartielun
WHERE RMonturesImp.N°Fac NOT IN (Select N°Fac From Requête2)
GROUP BY RMonturesImp.N°Fac;

sum over a field on a query

this should be a asked-before question, I searched but I could not find any answer on that. Sorry if it is duplicated. I have a query lets say:
my_query=session.query(Item).filter(somefilter)
Now, Item has a column, lets say counter, and I want to find the sum of this column of my_query.
I can do that like this:
sum=0
for row in query:
sum+=row.counter
but I don't this this is the efficient way of doing this specially in a large database. I know that this is possible: sqlalchemy simple example of `sum`, `average`, `min`, `max`, but this requires filtering on qry (borrowed from the page) which I have already given the filtered version my_query. I dont know if it is really more efficient to do the filtering again on top of qry v.s. using the for loop on my_query.
I had the same question. I asked on irc.freenode.org#sqlalchemy and inklesspen pointed me to Query#with_entities().
sum = my_query.with_entities(func.sum(Item.counter)).scalar()
There is a whole bunch of SQL "group" functions in sqlalchemy.func:
from sqlalchemy import func
my_query = session.query(func.sum(Item.counter)).filter(somefilter)

Efficient way to implement this ActiveRecord Query

I am using MySQL database and I have a datetime field inside it. In my rails application I have to fire a Query similar to the following,
MyTable.all(:conditions=>{my_date.to_date=>"2010-07-14"})
The my_date field is of datatype datetime. I should omit the time and should directly compare it with a date (but I am encountering an error near my_date.to_date due to obvious reasons). How to write an ActiveRecord Query for this scenario?
Thanks.
MyTable.all(:conditions=>["DATE_FORMAT(my_date, '%Y-%d-%m')=?", "2010-07-14"])
EDITED i think it should be
MyTable.all(:conditions=>["DATE_FORMAT(my_date, '%Y-%m-%d')=?", "2010-07-14"])
Here is an efficient solution if you index the date column:
d = "2010-07-14".to_date
MyTable.all(:conditions=>["my_date BETWEEN ? AND ?",
d.beginning_of_day, d.end_of_day)