I have sqlite base with a table Rating.
ID|Time|Clicks|
1|2020-04-02 20:20| 250
2|2020-04-03 18:20| 50
3|2020-04-04 22:50| 100
My class looks like this:
class Rating(base):
__tablename__ = 'Rating'
id = Column('ID', Integer, primary_key = True)
clicks = Column('Clicks', Integer)
time = Column('Time', Date)
I wanna show Clicks for a specific date.
date_i_need = datetime.date(2020, 4, 2)
q = test = session.query(Rating).filter_by(time = date_i_need).first()
I tried to change a type from Date to Datetime and Timestamp, but it always returns None.
Any guess?
You can specify datetime.date in statement. I think the problem is with syntax. Use ==:
Please try this:
date_i_need = datetime.date(2020, 4, 2)
q_test = session.query(Rating).filter(Rating.time == date_i_need).first()
Related
class Journal(Base):
__tablename__ = '_1SJOURN'
rid = Column("ROW_ID", Integer, primary_key=True)
journal_id = Column("IDJOURNAL", Integer)
iddoc = Column("IDDOC", String)
iddocdef = Column("IDDOCDEF", Integer)
datetime = Column("DATE_TIME_IDDOC", String)
table has field DATE_TIME_IDDOC like 200809305DU3F4 65P, first 8 chars is date. i need to select rows with date between s=20070503,e=20090503.
I tried:
filter(
and_(func.convert(sql.literal_column('DATE'), Journal.datetime, sql.literal_column('1,8')) > s,
func.convert(sql.literal_column('DATE'), Journal.datetime, sql.literal_column('1,8')) < e))
At first, why can't you split "datetime" column to two columns: datetime and "other_info"? Your table's structure is not optimized. If it will looks like below, it will be easier to implement what you want. Easier and rightly.
class Journal(Base):
__tablename__ = '_1SJOURN'
rid = Column("ROW_ID", Integer, primary_key=True)
journal_id = Column("IDJOURNAL", Integer)
iddoc = Column("IDDOC", String)
iddocdef = Column("IDDOCDEF", Integer)
datetime = Column("DATE_TIME", DateTime)
other = Column("OTHER", String)
# here I do not use `and_`, because it used by default
Session.query(Journal).filter(Journal.datetime > s, Journal.datetime < e)
But, if you really want it, that is your query. Raw SQL (for Postgresql, other DBMSes have the same functions but with another names):
SELECT * FROM journal WHERE to_timestamp(left(DATE_TIME_IDDOC, 8), 'YYYYMMDD') > '2008-10-01' AND to_timestamp(left(DATE_TIME_IDDOC, 8), 'YYYYMMDD') < '2010-01-20';
SQLAlchemy query:
filter_col = func.to_timestamp(func.left(Journal.datetime, 8), 'YYYYMMDD')
Session.query(Journal).filter(filter_col > s, filter_col < e)
and_(func.convert(sql.literal_column('datetime'),func.substring(Journal.datetime, 1,8)) > s ,
func.convert(sql.literal_column('datetime'), func.substring(Journal.datetime, 1, 8)) < e)).filter(
I have a django model:
class Field:
choice = models.CharField(choices=choices)
value = models.CharField(max_length=255)
In my database I have some cases where there are 3 "fields" with the same choice, and some cases where there is 1 field of that choice
How can I order the queryset so it returns, sorted by choice, but with all ones in a set of 3 at the start?
For example
[1,1,1,3,3,3,4,4,4,2,5] where 1,2,3,4,5 are possible choices?
This is the best I can do using django's ORM. Basically, just like in SQL, you have to construct a custom order_by statement. In our case, we'll place it in the SELECT and then order by it:
1) Get a list of choices sorted by frequency: [1, 3, 4, 2, 5]
freq_list = (
Field.objects.values_list('choice', flat=True)
.annotate(c=Count('id')).order_by('-c', 'choice')
)
2) Add indexes with enumerate: [(0,1), (1,3), (2,4), (3,2), (4,5)]
enum_list = list(enumerate(freq_list))
3) Create a list of cases: ['CASE', 'WHEN choice=1 THEN 0', ..., 'END']
case_list = ['CASE']
case_list += ["WHEN choice={1} THEN {0}".format(*tup) for tup in enum_list]
case_list += ['END']
4) Combine the case list into one string: 'CASE WHEN choice=1 THEN 0 ...'
case_statement = ' '.join(case_list)
5) Finally, use the case statement to select an extra field 'o' which will be corresponding order, then just order by this field
Field.objects.extra(select={'o': case_statement}).order_by('o')
To simplify all this, you can put the above code into a Model Manager:
class FieldManager(models.Manager):
def get_query_set(self):
freq_list = (
Field.objects.values_list('choice', flat=True)
.annotate(c=Count('id')).order_by('-c', 'choice')
)
enum_list = list(enumerate(freq_list))
case_list = ['CASE']
case_list += ["WHEN choice={1} THEN {0}".format(*tup) for tup in enum_list]
case_list += ['END']
case_statement = ' '.join(case_list)
ordered = Field.objects.extra(select={'o': case_statement}).order_by('o')
return ordered
class Field(models.Model):
...
freq_sorted = FieldManager()
Now you can query:
Field.freq_sorted.all()
Which will get you a Field QuerySet sorted by frequency of choices
You should make a function and detect which is repeated to select unique, then calling from mysql as a function over mysql
when i have a table in MySQL:
create table t
(
id integer primary key,
time datetime not null,
value integer not null
)
and an mapping class:
class T(Base):
__tablename__ = 't'
id = Column(INTEGER, primary_key=True, nullable=False, unique=True)
time = Column(DATETIME, nullable=False)
value = Column(INTEGER, nullable=False)
how can i select all values that have given month from this table using SQLAlchemy?
MySQL has the month function: select value from t where month(time) = 4
but SQLAlchemy has no month function.
Without loading all Ts into the session, one can use Functions to filter non April objects straight-away:
from sqlalchemy.sql import func
qry = session.query(T).filter(func.MONTH(T.time) == 4)
for t in qry:
print t.value
A very old question but a better answer is here:
from sqlalchemy import extract
session.query(T).filter(extract('month', T.time)==7).all()
This will return all the records into a database in July.
If for example you want the records from all April months irrespective of year or day:
for t in session.query(T):
if t.time.month == 4: print t.value
The situation is i have a database full of test results split into different test sets. Each test has a name, result , start time , start date , ... , what currently happens is over the week test sets can be run multiple times , giving multiple test results under a test set
Currently when i want to get the latest result of each test under a test set i am querying for the distinct test names, and then for each distinct name i am querying for that name and ordering by startDate and startTime to get the latest. This is a pain because when i have a test set with over 100 different tests it degrades substantially.
What im trying to do is to perform what i want in one call of django.objects...
Here is the mysql to effectively represent what i want to achieve:
select testName,result,MAX(startDate),MAX(startTime),othertestinfo from testset where testset_id = 'UniqueID' group by testName;
Im having a hard time trying to figure this out in django , if its even possible.
Any help would be much appreciated.
Thanks
Update 23/1/12
Models for what i am using.
class testCase(models.Model):
id = models.AutoField(primary_key=True)
testName = models.CharField(max_length=50)
result = models.CharField(max_length=50)
precision = models.CharField(max_length=10)
fileLocation = models.CharField(max_length=150)
testset_id = models.ForeignKey(testset)
machine = models.CharField(max_length=15)
startDate = models.DateField()
startTime = models.TimeField()
class testset(models.Model):
testsetID = models.CharField(max_length=100, primary_key=True)
testsetName = models.CharField(max_length=40)
platformName = models.CharField(max_length=15)
osName = models.CharField(max_length=15)
executionName = models.CharField(max_length=40)
version = models.CharField(max_length=10)
software = models.CharField(max_length=20)
runType = models.CharField(max_length=20)
You can give a try to the following:
t = testset.objects.values('testName').annotate(Max('startDate'),Max('startTime'))
This would give you a list of the objects' values-dictionaries containing key-value pairs of testName, startDate, startTime for the required condition.
You would get the condition fulfilled in this but you can try experimenting with this to get all the columns.
I have a table posts and it stores 3 types of post, Topic, Reply and Comment. Each one has its parent id.
# Single table inheritance
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('posts.id'))
discriminator = Column(String(1))
content = Column(UnicodeText)
added_at = Column(DateTime)
__mapper_args__ = {'polymorphic_on': discriminator}
class Topic(Post):
replies = relation("Reply")
__mapper_args__ = {'polymorphic_identity': 't'}
class Reply(Post):
comments = relation("Comment")
__mapper_args__ = {'polymorphic_identity': 'r'}
class Comment(Post):
__mapper_args__ = {'polymorphic_identity': 'c'}
And I'm using eagerload_all() to get all the replies and comments belong to one topic:
session.query(Topic).options(eagerload_all('replies.comments')).get(topic_id)
My question is, if I want to get only replies and those replies' comments in certain time period, for example, this week, or this month. How should I use filter to achieve this?
Thank you
The use of eagerload_all will only query for the children of an object Topic immediately rather on first request to the Replies and/or Comments, but since you load the Topic object into the session, all its related children will be loaded as well. This gives you the first option:
Option-1: Filter in the python code instead of database:
Basically create a method on the Topic object similar to
class Topic(Post):
...
def filter_replies(self, from_date, to_date):
return [r for r in self.replies
if r.added_at >= from_date
and r.added_at <= to_date]
Then you can do similar code on Replies to filter Comments or any combination of those. You get the idea.
Option-2: Filter on the database level:
In order to achieve this you need not load the Topic object, but filter directly on the Reply/Comment. Following query returns all Reply for a given Topic with a date filter:
topic_id = 1
from_date = date(2010, 9, 5)
to_date = date(2010, 9, 15)
q = session.query(Reply)
q = q.filter(Reply.parent_id == topic_id)
q = q.filter(Reply.added_at >= from_date)
q = q.filter(Reply.added_at <= to_date)
for r in q.all():
print "Reply: ", r
The version for the Comment is just a little bit more involved as you require an alias in order to overcome the SQL statement generation issue as all your objects are mapped to the same table name:
topic_id = 1
from_date = date(2010, 9, 5)
to_date = date(2010, 9, 15)
ralias = aliased(Reply)
q = session.query(Comment)
q = q.join((ralias, Comment.parent_id == ralias.id))
q = q.filter(ralias.parent_id == topic_id)
q = q.filter(Comment.added_at >= from_date)
q = q.filter(Comment.added_at <= to_date)
for c in q:
print "Comment: ", c
Obviously you can create a function that would combine both peaces into a more comprehensive query.
In order to achieve this week or this month type of queries you can either convert these filter into a date range as shown above or use the expression.func functionality of SA.