sqlalchemy func.min and where clause - sqlalchemy

i'm new of sqlalchemy,
i'm trying to write this select
select job_id,
machine_id,
state_id,
min(begin_time) as begin_time
from job
where machine_id = 2
and state_id = 2
the first time i've tried to write this..
session.query(Job).filter(and_(Job.begin_time==session.query(func.min(Job.begin_time)),
Job.state_id==2,Job.machine_id == 2)).all()
but return an empty list because it found another min begin_time row .
i've tried another way:
jobRecordSucces = session.query(Job).filter(Job.state_id==2,Job.machine_id == 2)
jobRecordSuccessivo = session.query(jobRecordSucces).filter(jobRecordSucces .begin_time==session.query(func.min(jobRecordSucces.begin_time)))
but the second query return me this error
InvalidRequestError: SQL expression, column, or mapped entity expected -
got '<sqlalchemy.orm.query.Query
object at 0x04491B10>'
thanks in advance :-)

Related

Converting N1Ql query having “where” clause with “IN” parameters into mapreduce views

I have a plain select query for which mapreduce view is already present.
Query:
select count(*) from `my-bucket` where type = 'Order' and status = 'CREATED' and timestamp > 1535605294320 and timestamp <= 1535605594320
view:
function (doc, meta) {
if (doc._class == "com.myclass.Order"){
emit([doc.type,doc.status, doc.timestamp], null);
}
}
Keys for querying the view:
Start key : ["Order","CREATED",1535605294320]
End key : ["Order","CREATED",1535605594320]
Requirement: Now, we would want this view to support a query having IN clause on status parameter. Also, we would like to add additional parameters supporting IN parameters. Sample N1Ql would be like below.
select count(*) from `my-bucket` where type = 'Order' and orderType IN ["TYPE-A","TYPE-B","TYPE-C"]and status IN ['CREATED',""READY,"CANCELLED"] and timestamp > MILLIS("2016-05-15T03:59:00Z") and timestamp <= MILLIS("2017-05-15T03:59:00Z")
How to write a query on view to accomplish this? Only solution comes to my mind is to fire multiple (lets says x) queries on views
where x = m1*m2*....*mn
AND m1=number of paremeters in first IN clause
AND n=number of IN clauses.
Is there any better solution like executing this query in batch (using java SDK) or a single mapreduce query?

How to make where condition always be true with field =?

I have a sql statement follow:
select * from table where id = ?
Now, problem is, l don't know whether front end will send me the value of id, if it did, this sql seem like id = 1, and if not, sql should be like id = true(fake code) to find all data
How could I write my sql?
Or, It is fundamentally wrong?
This is normally handled by using logic such as this:
select *
from table
where id = ? or ? is null;
If you don't want to pass the parameter twice or use named parameters:
select t.*
from table t cross join
(select ? as param) params
where id = params.param or params.param is null;
If you want to return all ids if the passed-in value does not exist:
select t.*
from table t
where id = ? or
not exists (select 1 from table t2 where t2.id = ?);
What you can try doing is in your code, write a function for fetching a specific record, and another function for fetching all the records from your table.
In PHP, it could be something like:
// Fetching a specific record
function getCustomerRecord($customerId) {
// Code to fetch specific record from database
}
// Fetching all records
function getAllCustomerRecords() {
// Code to fetch all records from database
}
In the function where you process requests received, check first if a value for id was passed. If a value for id was passed, call the function to fetch a specific record, making sure to pass along the value you received as an argument. Otherwise, call the function to fetch all the records from your table.
You can try doing this to get your right sql statement in PHP
function GetSqlStatement($id){
return $sql = "select * from table where id = ".$id.";";
}

MySQL - top product exported by each state based on the sum of individual export_values

I am trying to write a query in Peewee with a MySQL database to return the top product exported by each state based on the sum of the export_values for a given product-state pair. I am wondering what the most optimal SQL query to achieve that would be. Here's the schema of the table I care about:
Trade
- product (varchar)
- state (varchar)
- export_value (numeric)
...
The fields I need to select are: state, product, and total_export_value.
Any guidance on how to design this query? If possible, also on how to translate it into Peewee (I am very new to it).
EDIT:
Here's the Peewee query I've tried:
subquery = (
models.Trade.select(
models.Trade.state.alias("state_1"),
models.Trade.product.alias("product_1"),
fn.SUM(models.Trade.export_value).alias("export_value_1")
).where(
models.Trade.origin_country == origin_country,
models.Trade.year == args["year"]
).group_by(
models.Trade.state,
models.Trade.product
).alias("subquery")
)
query = (
models.Trade.select(
models.Trade.state,
models.Trade.product,
fn.MAX(subquery.c.export_value_1).alias("export_value")
).join(
subquery, on=(
(models.Trade.state == subquery.c.state_1) &
(models.Trade.product == subquery.c.product_1)
)
).group_by(
models.Trade.state
)
)
It's not working for my needs because MySQL is not selecting the appropriate product, but the state and total_export_value are selected just fine. I suspect it's because of the way it's joining the two queries and that product is not used in the GROUP BY of the query.

How to get the last updated row using a single query

I searched enough before posting it.
My table structure:
aid | bid | cid | did |
Where aid, bid together are the primary keys.
When I update the value of cid using a where clause for aid, bid I also want to get the did value of the updated row.
Something like this:
$this->db->set('cid', 1, FALSE)
->where(array(
'aid' => $a_id,
'bid' => $b_id
))
->update('my_table')
->select('did');
The above query says:
Fatal error: Call to a member function select() on a non-object in...
I tried this:
How to get ID of the last updated row in MySQL?
Which is like 3 queries.
I'd suggest fetching the values you're about to update, store their IDs in an array, and run an UPDATE with a WHERE id IN (1, 2, ...).
What you're trying to do is not supported by MySQL. You'll need to run at least 2 queries, and since you're fetching the values the first time and already know what values you're updating, then you can also recreate the new row and it's values without using a query after UPDATE.
In your given example:
$this->db->set('cid', 1, FALSE)
->where(array(
'aid' => $a_id,
'bid' => $b_id
))
->update('my_table')
->select('did');
set(), where() and also select() returns an object that builds on the query. However update() return a value which is the results and doesn't have a function called select() and not set() and where() for that matter.

Return zero when records not found

Im making a table generator as a school project.
In MySQL I have 3 tables namely process,operation,score. Everything looked fine until i tested out my "ADD column" button in the web app.
Previous saved data should be read properly but also include the new column in the format, problem is the previous data queried does not include any values for the new table, so I intended it to return a score of 0 if no records were found, tried IFNULL & COALESCE but nothing happens(maybe im just using it wrong)
process - processID, processName
operation - operationID, operationName
score - scoreID, score, processID, operationID, scoreType (score
types are SELF,GL,FINAL)
ps = (PreparedStatement)dbconn.prepareStatement("SELECT score FROM score WHERE processID=? and operationID=? and type=?ORDER BY processid");
here's a pic of a small sample http://i50.tinypic.com/2yv3rf9.jpg
The reason that IFNULL doesn't work is that it only has an effect on values. A result set with no rows has no values, so it does nothing.
First, it's probably better to do this on the client than on the server. But if you have to do it on the server, there's a couple of approaches I can think of.
Try this:
SELECT IFNULL(SUM(score), 0) AS score
FROM score
WHERE processID=? and operationID=? and type=?
ORDER BY processid
The SUM ensures that exactly one row will be returned.
If you need to return multiple rows when the table contains multiple matching rows then you can use this (omitting the ORDER BY for simplicity):
SELECT score
FROM score
WHERE processID = ? and operationID = ? and type = ?
UNION ALL
SELECT 0
FROM (SELECT 0) T1
WHERE NOT EXISTS
(
SELECT *
FROM score
WHERE processID = ? and operationID = ? and type = ?
)