I have the following SQL query (MySQL database)
SELECT distinct filename, DATE(created)
FROM FileTable
WHERE created > DATE_SUB(NOW(), INTERVAL 7 DAY);
My table definition:
**FileTable**
id : PK
filename :varchar
created :date
How to write an equivalent SQLAlchemy query for the above SQL statement and fetch results?
I tried this
myvar=session.query(FileTable).filter(created > DATE_SUB(NOW(), INTERVAL 7 DAY)).first()
return x.filename,x.DATE(created) for x in myvar
But it says the syntax is invalid. Please help. Thanks and regards :)
I suggest you are looking for magic func of sqlalchemy.sql.functions. Here is an example:
from sqlalchemy import *
metadata = MetaData()
FileTable = Table(
'FileTable',
metadata,
Column('id', Integer, primary_key=True),
Column('filename', String),
Column('created', DateTime))
print select([
distinct(FileTable.columns.filename),
func.date(FileTable.columns.created)
]).where(
FileTable.columns.created > func.date_sub(func.now(), 7))
# Output:
# SELECT DISTINCT "FileTable".filename, date("FileTable".created) AS date_1
# FROM "FileTable"
# WHERE "FileTable".created > date_sub(now(), :date_sub_1)
You can try this but it may results the rows those filenames are distinct in each dates(I've tested in PostgreSQL).
query = session.query(FileTable.filename.distinct(),
func.date(FileTable.created))\
.filter(created > func.adddate(func.now(), -7))
return query.all()
If you find yourself wanting to retrieve only single row per single filename then you can transform query to fetch filenames and its (in example) latest created times like below:
query = session.query(FileTable.filename,
func.date(func.max(FileTable.created)))\
.filter(created > func.adddate(func.now(), -7))\
.group_by(FileTable.filename)
return query.all()
Related
Is it possible to limit the execution of an SQL CRUD-statement with a condition that is completely unrelated to the table it is working on?
E.g. execute the UPDATE only if there is a special date.
UPDATE tabfoo SET name="santa" where id="123" // only if day = 31.12.
I like to have this inside a single statement. I know how to do it inside a script.
Me platform would be MySql or SqLite.
For SQLite you can use the function strftime()
WHERE id = '123'
AND strftime('%d.%m', CURRENT_DATE) = '31.12'
and for MySql the function DATE_FORMAT():
WHERE id = '123'
AND DATE_FORMAT(CURRENT_DATE, '%d.%m') = '31.12'
In MySQL the problem can be solved next way:
UPDATE tabfoo
SET name="santa" WHERE
id="123" AND MONTH(CURDATE()) = 12 AND DAY(CURDATE()) = 31; // only if day = 31.12.
or
UPDATE tabfoo
SET name="santa" WHERE
id="123" AND DATE_FORMAT(CURDATE(), '%d.%m') = '31.12';
For SQLite you can find alternative function
You can try
UPDATE tabfoo SET name="santa" where id="123" and day = 31.12.
otherways you may try a sql stored procedure.
if-else doku
I have to update table which have column data type as integer, but I have an input as a datetime. this is query that i hve writen
UPDATE T_SCH_ETAX_TEMP SET CURRTIME = UNIX_TIMESTAMP
(TIMEDIFF("(SELECT DATE_FORMAT(?,'%H:%i:%s') TIMEONLY)", "(SELECT
DATE_FORMAT(CURRENT_TIMESTAMP,'%H:%i:%s') TIMEONLY)"), LENGTHTIME =
UNIX_TIMESTAMP(TIMEDIFF("(SELECT DATE_FORMAT(?,'%H:%i:%s')
TIMEONLY)", "(SELECT DATE_FORMAT(CURRENT_TIMESTAMP,'%H:%i:%s')
TIMEONLY)")
any one can help how to convert timestamp result as an integer so I can update the table using SSIS
I could be wrong, please forgive me if I am, but you seem to want something simpler:
UPDATE T_SCH_ETAX_TEMP
SET CURRTIME = UNIX_TIMESTAMP(
TIMEDIFF(TIME(?),
TIME(CURRENT_TIMESTAMP))),
LENGTHTIME = UNIX_TIMESTAMP(
TIMEDIFF(TIME(?), TIME(CURRENT_TIMESTAMP)));
Which would only require 2 parameters ('ss');
If this is the case, in can be simplified to:
UPDATE T_SCH_ETAX_TEMP
SET CURRTIME = UNIX_TIMESTAMP(
TIMEDIFF(?,
CURRENT_TIMESTAMP)),
LENGTHTIME = UNIX_TIMESTAMP(
TIMEDIFF(?, CURRENT_TIMESTAMP));
if you pre-format your parameter strings
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
I am trying to delete 1 month old records from my table using domain.executeUpdate as follows
Bugrerun.executeUpdate("delete Bugrerun b where b.complete = 1 and b.date
< date_sub(curdate(), INTERVAL 1 MONTH) ")
i am trying to use a MySQL date function inside the query.
But this fails with the error
org.hibernate.hql.ast.QuerySyntaxException: unexpected token: 1 near line 1
, column 97
How can we use the My SQL date time functions inside executeUpdate statements
Note that this table has lot of data so fetch and delete individual records will not work
You can try with the below query, just need to validate whether the HQL functions are supported in MySQL dialect:
Bugrerun.executeUpdate("delete Bugrerun b \
where b.complete = 1 \
and month(current_date()) > month(b.date) \
or year(current_date()) > year(b.date)")
You could implement your own Database dialect to include that functionality.
Another option is to do this:
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.MONTH, -1);
Bugrerun.executeUpdate("delete Bugrerun b where b.complete = 1 and b.date
< :oneMonthAgo", [oneMonthAgo: cal.time])
Not all mysql functions are available. You can take a look at MySQLDialect that is used by hibernate (and grails) to see the functions you have available for you:
http://grepcode.com/file/repository.springsource.com/org.hibernate/com.springsource.org.hibernate/3.3.1/org/hibernate/dialect/MySQLDialect.java#MySQLDialect
If you want, you can try to use Groovy SQL to execute a SQL statement instead of an HQL statement. If you do that, in your controller or service you should declare a dataSource attribute so you get DataSource injected:
class MyController {
DataSource dataSource
def execSql(){
def sql = new Sql(dataSource)
sql.execute("delete from bugrerun where complete = 1 and date < date_sub(curdate(), INTERVAL 1 MONTH) ")
render "done"
}
}
#necessary import goes here
engine = sqlalchemy.create_engine('mysql://root#127.0.0.1/test',echo=False)
print 'Engine created'
connection=engine.connect()
metadata=MetaData(engine)
metadata.bind=engine
Session = sessionmaker(bind=engine)
session = Session()
mapping = Table('mapping',metadata,autoload=True)
class Mapping(object):
pass
MappingMapper=mapper(Mapping,mapping)
Now i am able to write basic query for insert,update,delete,filter etc.
Q:1 I need to write complex query, where i do derive new columns based on existing columns. Ex. ColA,ColB is there on table, ColC is not part of table structure.
Select (ColA+ColB) as ColC from table where ColC > 50 order by ColC.
I am clueless how to convert above like query with SqlAlchemy. How to map, how to retrieve.
The easiest is to useHybrid Attributes.
In your case, just change the declaration of the class to the following:
from sqlalchemy.ext.hybrid import hybrid_property
class Mapping(object):
#hybrid_property
def ColC(self):
return self.ColA + self.ColB
Then the query:
qry = session.query(Mapping).filter(Mapping.ColC > 80)
will generate SQL:
SELECT mapping.id AS mapping_id, ...
FROM mapping
WHERE mapping."ColA" + mapping."ColB" > ?