sum with condition in django query - mysql

We want to wrtie this query in django please
SELECT sum(recommended='1') AS YES,sum(recommended='0') AS NO FROM `rating` WHERE applied_users = 32500
we have no idea how to use in sum "= 1"
Rating.objects.filter(applied_id = 32500).aggregate(YES=Sum('recommended'))

Use aggregate with case in django, it will return you single result with annotate it will return you a multiple records
https://docs.djangoproject.com/en/1.11/ref/models/conditional-expressions/
from django.db.models import Sum, Case, When, IntegerField
Rating.objects.filter(applied_id = 32500)
.aggregate(
yes=Sum(
Case(
When(recommended='1', then=1),
output_field=IntegerField()
)
),
no=Sum(
Case(
When(recommended=0,then=1),
output_field=IntegerField()
)
)
)

First refer this : https://docs.djangoproject.com/en/1.11/ref/models/conditional-expressions/
from django.db.models import Sum, Case, When, IntegerField
OR
from django.db.models.aggregates import Sum
from django.db.models.expressions import Case, When
ratings = Rating.objects
.annotate(yes_count=Sum(Case(When(recommended='1', then=1),output_field=IntegerField())))
.annotate(no_count=Sum(Case(When(recommended='0', then=1),output_field=IntegerField())))
.filter(applied_id = 32500)

Related

Using mysql '%' in date_format in Jupyter notebook

I try to use date_format in Jupyter notebook in my sql query to get the correct data but Jupyter throws the following error:
sql = "SELECT DATE_FORMAT(issues.created_on, "%Y") as YEAR, issues.tracker_id as Ticketgrund, count(*) FROM issues where issues.project_id = '2' group by YEAR, Ticketgrund;"
^
SyntaxError: invalid syntax"
Here is my cell:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sqlalchemy
session = sqlalchemy.create_engine("mysql+pymysql://user:pwj#ip/DB")
sql = "SELECT DATE_FORMAT(issues.created_on, "%Y") as YEAR, issues.tracker_id as Ticketgrund, count(*) FROM issues where issues.project_id = '2' group by YEAR, Ticketgrund;"
df = pd.read_sql_query(sql,session)
df.head(20)
The sql query runs without errors but not in jupyter. Escaping the %, which I assume to be the reason for error, does not change anything.
What can I do?
Escape the % with % (and use single quotes inside double quotes):
sql = "SELECT DATE_FORMAT(issues.created_on, '%%Y') as YEAR, issues.tracker_id as Ticketgrund, count(*) FROM issues where issues.project_id = '2' group by YEAR, Ticketgrund;"
Alternatively, use the date_format function available in SQLAlchemy. Here is a brief example:
from sqlalchemy import func
from sqlalchemy import MetaData, Table, Column
from sqlalchemy import select
from sqlalchemy import Integer, String, DateTime
md = MetaData()
mytable = Table(
"employees",
md,
Column("emp_no", Integer, primary_key=True),
Column("first_name", String(30)),
Column("last_name", String(30)),
Column("hire_date", DateTime),
)
row = session.execute( select(mytable.c.first_name, func.date_format(mytable.c.hire_date, "%Y") ) ).first()
print(row)

ORA-00979 when using group_by with sqlalchemy

I have a query, which makes a count of the total tasks based on the month of creation, however sqlalchemy is bringing me the following error:
sqlalchemy.exc.DatabaseError: (cx_Oracle.DatabaseError) ORA-00979
This is my sqlalchemy query:
tasks_by_month = (
db.session.query(
func.to_char(Task.creation_time, "MM").label("month"),
func.count(Task.id).label("count"),
)
.group_by(func.to_char(Task.creation_time, "MM"))
.order_by(text("month asc"))
.all()
)
This is the query in sqldeveloper:
SELECT
TO_CHAR(TA.CREATION_TIME, 'MM') AS MONTH,
COUNT(TA.ID)
FROM
TASKS TA
GROUP BY
TO_CHAR(TA.CREATION_TIME, 'MM')
ORDER BY
MONTH
I am expecting the following result
Thanks for help
I managed to solve the problem by changing func.to_char(Task.creation_time, "MM").Label ("month") to extract('month', Task.creation_time).label("month").
tasks_by_month = (
db.session.query(
extract('month', Task.creation_time).label("month"),
func.count(Task.id).label("count"),
)
.group_by(extract('month', Task.creation_time))
.order_by(text("month asc"))
.all()
)
Thanks :)

How to create "ORDER BY Column = 'Value'" query with SQLAlchemy

I am new to SQLAlchemy & wanted to create an SQLAlchemy query equivalent to "order by exact match first".
Below is the SQL:
select word from dictionary where word like '%Time%' order by (word = 'Time') desc;
This is my SQLAlchemy equivalent.
Dictionary.query.with_entities ( Dictionary.word )
.filter(Dictionary.word.like("%{}%".format("Time")))
.order_by(Dictionary.word == "Time")
But it throws an error at "order_by": SyntaxError: keyword can't be an expression. How to solve it ?
Solved it.
from sqlalchemy.sql import func
.order_by(Dictionary.word == q,func.length(Dictionary.word))

Using GROUP_CONCAT with other annotations in Django

I use an annotation which counts upvotes/downvotes while returning a list of articles:
queryset = queryset.annotate(
upvotes_count=models.Sum(
models.Case(
models.When(likes__like_state=1, then=1),
default=0,
output_field=models.IntegerField()
)
)
).annotate(
downvotes_count=models.Sum(
models.Case(
models.When(likes__like_state=-1, then=1),
default=0,
output_field=models.IntegerField()
))
)
But each article also has a few categories as ManyToMany related field and I needed to return those categories comma-separated, so I wrote this function:
class GroupConcat(models.Aggregate):
function = 'GROUP_CONCAT'
template = "%(function)s(%(distinct)s %(expressions)s %(separator)s)"
def __init__(self, expression, distinct=False, separator=', ', **extra):
super(GroupConcat, self).__init__(
expression,
distinct='DISTINCT' if distinct else '',
separator="SEPARATOR '%s'" % separator,
output_field=models.CharField(),
**extra
)
And added it to my annotation:
queryset = queryset.annotate(category=GroupConcat('categories__name'))
It works fine but upvotes_count and downvotes_count went crazy and started to multiply(!) results by amount of categories.
So the question is: "Is there a way to use GROUP_CONCAT in Django without breaking down SUM annotations?"
Very nice solution.
But to operate with group by field you should use order_by statement.
for example:
Store.objects.all().values('value').order_by('value').annotate(stores=GroupConcat('id'))
would generate sql statement
SELECT store.value, GROUP_CONCAT(store.id SEPARATOR ",") AS
stores FROM store WHERE store.value > 0 GROUP BY
store.value ORDER BY store.value ASC
and result would be
value, stores
1 "16,27"
Without order_by it would be like this:
SELECT store.value, GROUP_CONCAT(store.id SEPARATOR ",") AS
stores FROM store WHERE store.value > 0 GROUP BY store.id
ORDER BY store.value ASC
and result would be
value, stores
1 16
2 27

SQLAlchemy MySQL IF Statement

I'm in the middle of converting an old legacy PHP system to Flask + SQLAlchemy and was wondering how I would construct the following:
I have a model:
class Invoice(db.Model):
paidtodate = db.Column(DECIMAL(10,2))
fullinvoiceamount = db.Column(DECIMAL(10,2))
invoiceamount = db.Column(DECIMAL(10,2))
invoicetype = db.Column(db.String(10))
acis_cost = db.Column(DECIMAL(10,2))
The query I need to run is:
SELECT COUNT(*) AS the_count, sum(if(paidtodate>0,paidtodate,if(invoicetype='CPCN' or invoicetype='CPON' or invoicetype='CBCN' or invoicetype='CBON' or invoicetype='CPUB' or invoicetype='CPGU' or invoicetype='CPSO',invoiceamount,
fullinvoiceamount))) AS amount,
SUM(acis_cost) AS cost, (SUM(if(paidtodate>0,paidtodate,invoiceamount))-SUM(acis_cost)) AS profit FROM tblclientinvoices
Is there an SQLAlchemyish way to construct this query? - I've tried googling for Mysql IF statments with SQlAlchemy but drew blanks.
Many thanks!
Use func(documentation) to generate SQL function expression:
qry = select([
func.count().label("the_count"),
func.sum(func.IF(
Invoice.paidtodate>0,
Invoice.paidtodate,
# #note: I prefer using IN instead of multiple OR statements
func.IF(Invoice.invoicetype.in_(
("CPCN", "CPON", "CBCN", "CBON", "CPUB", "CPGU", "CPSO",)
),
Invoice.invoiceamount,
Invoice.fullinvoiceamount)
)
).label("amount"),
func.sum(Invoice.acis_cost).label("Cost"),
(func.sum(func.IF(
Invoice.paidtodate>0,
Invoice.paidtodate,
Invoice.invoiceamount
))
- func.sum(Invoice.acis_cost)
).label("Profit"),
],
)
rows = session.query(qry).all()
for row in rows:
print row