Given a table
class Order(db.Model):
created_at = db.Column(db.DateTime)
days = db.Column(db.Integer)
I need to compose a query with FROM statement like this: Order.created_at + Order.days < datetime.now(). The simplest way doesn't work, since the result of addition integer to datetime is double :) This conclusion I've made after practical experiment with MySQL.
After searching a little I've found out correct SQL statement for MySQL which solves described issue:
SELECT *
FROM orders o
WHERE o.created_at + INTERVAL o.days DAY < '2014-06-10 14:22:00';
And what I'd like to ask is how to code the query above for sqlalchemy filter?
I've found one article how to use Intervals here on stackoverflow, but DATEADD is missing in MySQL and I have no ideas where I need to bind an Interval.
Sorry for my poor English, I hope I could explain my problem correct :)
UPD: Maybe the right thing to define days as Interval, but currently it's not an option.
MySQL has a function called TIMESTAMPADD which seems to do what you want. Here's how to use it in a query.
session.query(Order).filter(func.timestampadd(text('DAY'), Order.days, Order.created_at) < datetime(2014, 6, 10, 14, 22))
from sqlalchemy import select, func
query = (session.query(Orders).filter(
func.DATEADD('day', Orders.days, Orders.created_at) == '2014-06-10 14:22:00'))
Old question, but for anyone using PSQL / SQlAlchemy 1.0.10+ you can use the below:
from sqlalchemy.sql import cast
db = SQLAlchemy() # Instantiated
Order.query.filter(
Order.created_at > cast('1 DAY', db.Interval) * Order.day
).all()
Related
I have a table in the sqlite with column "telegram_id"
I want to get all unique records of this column
def get_all_telegram_ids():
'''Returns all telegram_id from DB'''
#rows = cursor.execute("SELECT DISTINCT telegram_id FROM locations").fetchall()
rows = Locations.select(Locations.telegram_id).distinct()
print(rows)
return rows
but this code does not work :-(
Seems to be working fine:
import random
from peewee import *
db = SqliteDatabase(':memory:')
class Location(Model):
telegram_id = IntegerField()
class Meta:
database = db
db.create_tables([Location])
for i in range(100):
Location.create(telegram_id=random.randint(1, 10))
q = Location.select(Location.telegram_id).distinct()
for l in q:
print(l.telegram_id)
Prints 1-10 with some variation and no duplicates.
Alternative invocation that also works:
q = Location.select(fn.DISTINCT(Location.telegram_id))
for l in q:
print(l.telegram_id)
but this code does not work :-(
Have you considered reading the documentation
By specifying a single value of True the query will use a simple SELECT DISTINCT. Specifying one or more columns will result in a SELECT DISTINCT ON.
So it doesn't seem like you can just call distinct() with no parameters, it's always at least select(True).
Also when asking questions about things not working, it's usually a good idea to explain the ways in which it is not working e.g. the error you get if there is one, or your expectations versus what you're observing.
Even more so when you don't come close to providing a minimal reproducible example.
If you would want to filter a table by the length of one of its relationships (the number of rows, which exists in a relationship), how would you do that?
I want the filter statement to function like this:
Table.query.filter(Table.relationship.length == relationship_length)
Here's an example of application:
Family.query.filter(Family.children.length == amount_of_children)
As stated by Tim Roberts, the way to do it in plain SQL would be:
GROUP BY familyid HAVING count(*) > length
If there isn't any function for that in sqlalchemy, how can it be done then?
As stated by Tim Roberts, the way to do it in plain SQL would be:
GROUP BY tableid HAVING count(*) > length
In sqlalchemy, that would be written like this:
from sqlalchemy import func
Table.query.join(Table.relationship).group_by(Table.id).having(func.count() == relationship_length)
And for the example, searching for a family with a specific amount of children:
from sqlalchemy import func
Family.query.join(Family.children).group_by(Family.id).having(func.count()==amount_of_children)
I have a SQLite3 table that collects data from a gym booking form; all the data goes into one table - Name, Email, Day, Exercise Class, Class Time.
If it is possible, I would like to find a way to get all from Name if Day, Exercise Class & Class Time are equal to a selected value.
I am using Flask so once I can do this the data would then be used to generate a new HTML page (which would be the registration checklist page for the gym tutor).
I am pretty sure this is incorrect, but this is the general idea of what I would like to achieve..
db.execute("SELECT * FROM GymTable WHERE (Day == "Monday", Ex_Class == "BoxFit", Ex_Time == "0745-0845"))
the correct query in this case would be:
db.execute("SELECT * FROM GymTable WHERE Day = 'Monday' and Ex_Class = 'BoxFit' and Ex_Time = '0745-0845'")
You may find these two tutorials on the SQL WHERE clause and SQL AND, OR, NOT Operators helpful. Notice first that the equal operator is = instead of ==. This query needs AND between column filters. The WHERE clause should not be enclosed in (). You may find the python sqlite3 doc useful as well.
To better illustrate:
db.execute( "
SELECT name
FROM gymtable
WHERE day = 'Monday'
AND ex_class = 'BoxFit'
AND ex_time = '0745-0845'
");
I'm using SqlAlchemy to store some objects with a DateTime field:
my_date = Field(DateTime())
I'd like to run a query to retrieve the most recent few objects (Entities with the my_date field that are the most recent).
I've tried the following:
entities = MyEntity.query.order_by(MyEntity.time).limit(3).all()
entities = MyEntity.query.order_by(-MyEntity.time).limit(3).all()
But these queries return the same objects in the same order. The SqlAlchemy documentation notes the use of the '-' to reverse the order, but I'm surely missing something here.
Can anyone help?
You can do it like this:
entities = MyEntity.query.order_by(desc(MyEntity.time)).limit(3).all()
You might need to:
from sqlalchemy import desc
Here's some documentation.
Another option is this:
stmt = select([users_table]).order_by(users_table.c.name.desc())
entities = MyEntity.query.order_by(MyEntity.my_date.desc()).limit(3).all()
should work.
You can use like this
from sqlalchemy import desc
db.session.query(MyEntity).order_by(desc(MyEntity.time))
I have a model similar to the following:
class Review(models.Model):
venue = models.ForeignKey(Venue, db_index=True)
review = models.TextField()
datetime_created = models.DateTimeField(default=datetime.now)
I'd like to query the database to get the total number of reviews for a venue grouped by day. The MySQL query would be:
SELECT DATE(datetime_created), count(id)
FROM REVIEW
WHERE venue_id = 2
GROUP BY DATE(datetime_created);
What is the best way to accomplish this in Django? I could just use
Review.objects.filter(venue__pk=2)
and parse the results in the view, but that doesn't seem right to me.
This should work (using the same MySQL specific function you used):
Review.objects.filter(venue__pk=2)
.extra({'date_created' : "date(datetime_created)"})
.values('date_created')
.annotate(created_count=Count('id'))
Now that Extra() is being depreciated a more appropriate answer would use Trunc such as this accepted answer
Now the OP's question would be answered as follows
from django.db.models.functions import TruncDay
Review.objects.all()
.annotate(date=TruncDay('datetime_created'))
.values("date")
.annotate(created_count=Count('id'))
.order_by("-date")
Just for completeness, since extra() is aimed for deprecation, one could use this approach:
from django.db.models.expressions import DateTime
Review.objects.all().\
annotate(month=DateTime("timestamp", "month", pytz.timezone("Etc/UTC"))).\
values("month").\
annotate(created_count=Count('id')).\
order_by("-month")
It worked for me in django 1.8, both in sqlite and MySql databases.
If you were storing a date field, you could use this:
from django.db.models import Count
Review.objects.filter(venue__pk = 2)
.values('date').annotate(event_count = Count('id'))
Because you're storing datetime, it's a little more complicated, but this should offer a good starting point. Check out the aggregation docs here.
Also you can define custom function:
from django.db.models.expressions import Func
# create custom sql function
class ExtractDateFunction(Func):
function = "DATE" # thats the name of function, the way it mapped to sql
# pass this function to annotate
Review.objects.filter(venue__pk=2)
.annotate(date_created=ExtractDateFunction("datetime_created"))
.values('date_created')
.annotate(created_count=Count('id'))
Just make sure that your DB engine supports DATE function