sqlalchemy how to cast mixed field to date? - sqlalchemy

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(

Related

Converting DateandTime to time and comparing with DB for validation

I want to write a validation in such a way that my query should result true if same CCN and date already exist in DB, from JSON and IN DB datetime is saved in "yyyy-MM-dd HH:mm:ss", but in my validation i need to take only date[yyyy-MM-dd] and compare.
I am new to spring boot
This is what i have in my model class
#JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
#Temporal(TemporalType.DATE)
private Date datetime;
Repository for my class
#Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM TABLEX c WHERE c.ccn = :ccn and c.datetime= :datetime")
boolean isExistbyCcnAndDate(#Param("ccn") String conveyancereferencenumber, #Param("datetime") #DateTimeFormat(pattern = "yyyy-MM-dd") Date date);
When i try this it gives result as always false.
This is how i am passing values to repository
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateString = sdf.format(model.getDatetime());
convertedDate = sdf.parse(dateString);
isExistCcnAndDate=repository.isExistbyCcnAndDate(model.getCcn(),convertedDate);
Check out my sqlfiddle.
http://sqlfiddle.com/#!9/5305eb/3
Using sql fiddle this will work:
Create shema:
create table c(datetime DATETIME, ccn TEXT)
insert into c (datetime, ccn) values ('2020-01-01 10:10:50' , 'a');
Try to read and filter step by step:
select * from c;
select * from c where c.datetime = '2020-01-01 10:10:50';
select * from c where date(c.datetime)= date('2020-01-01');
As I already said, whether you can use date(), DATE() or whatever depends on your server, sqlfiddle is MySQL.

SQL Alchemy and datetime

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()

sqlalchemy - select records by month in 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

How to set filter to get children in certain time period by eagerload_all() at SqlAlchemy

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.

Creating LINQ to SQL for counting a parameter

I'm trying to translate a sql query into LINQ to SQL. I keep getting an error "sequence operators not supported for type 'system.string'" If I take out the distinct count part, it works. Is it not because I'm using the GROUP BY?
SELECT COUNT(EpaValue) AS [Leak Count], Location, EpaValue AS [Leak Desc.]
FROM ChartMes.dbo.RecourceActualEPA_Report
WHERE (EpaName = N'LEAK1') AND (Timestamp) > '20100429030000'
GROUP BY EpaValue, Location
ORDER BY Location, [Leak Count] DESC
Dim temp = (From p In db2.RecourceActualEPA_Reports _
Where (p.Timestamp >= str1stShiftStart) And (p.Timestamp < str2ndShiftCutoff) _
And (p.EpaName = "Leak1") _
Select p.EpaName.Distinct.Count(), p.Location, p.EpaValue)
p.EpaName seems to be a string, not a collection so you can't apply Count() there.
Here is the query you're trying to build (according to your SQL query) using LINQ (I'm not familiar with VB, so the query is written in C#):
var temp =
db2.RecourceActualEPA_Reports
.Where(p =>
p.Timestamp >= str1stShiftStart &&
p.Timestamp < str2ndShiftCutoff &&
p.EpaName == "Leak1"
).GroupBy(p => new { Key1 = p.EpaValue, Key2 = p.Location })
.Select(g => new
{
Count = g.Count(),
Value = g.Key.Key1,
Location = g.Key.Key2
}).OrderBy(i => new { i.Location, i.Count });
And please, in the future format and highlight your code using this, not (or not only) using VS/Management Studio.
Here is how it is formatted in SQL and in Visual Studio
SQL
SELECT COUNT(EpaValue) AS [Leak Count], Location, EpaValue AS [Leak Desc.]
FROM ChartMes.dbo.RecourceActualEPA_Report
WHERE (EpaName = N'LEAK1') AND (Timestamp) > '20100429030000'
GROUP BY EpaValue, Location
ORDER BY Location, [Leak Count] DESC
VB
Dim temp = (From p In db2.RecourceActualEPA_Reports _
Where (p.Timestamp >= str1stShiftStart) And (p.Timestamp < str2ndShiftCutoff) _
And (p.EpaName = "Leak1") _
Select p.EpaName.Distinct.Count(), p.Location, p.EpaValue)