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?
Related
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 can i do these in laravel query where clause?
select * from table_samples where 1 = id
// basically i can do like where id = 1
select * from table_samples where 1000 > rate
// basically i can do like where rate < 1000
select * from table_samples where 'bogart' = name
// basically i can do like where name = "bogart"
My point is if you interchange the column and value its working on mysql, but if i do this in laravel where clause it doesn't work?
Something like
TableSample::where('1','id')->first();
TableSample::where('1000','>','rate')->first();
TableSample::where('bogart','name')->first();
// throws an error undefined column name 1, 100, and bogart.
// I know laravel . These are the correct query
TableSample::where('id','1')->first();
TableSample::where('rate','<','1000')->first();
TableSample::where('name','bogart')->first();
Is there any where clauses functions in laravel that can accept or determine if you try to interchange the value and column?
You yan use DB::raw() for this.
TableSample::whereRaw('? = id', [1])->first();
Just make sure you use parameter substitution like above to prevent creating sql injection vulnerabilities.
https://laravel.com/docs/5.6/queries#raw-expressions
The whereRaw and orWhereRaw methods can be used to inject a raw where clause into your query
TableSample::whereRaw('1 = id')->first();
https://laravel.com/docs/5.6/queries#raw-methods
I've got a use case where I need to query for Appointment records based on their created_at or their start_on values. There are two types of appointments: 'Estimate' and 'GLA (go look at)', represented by a type field with values 0 and 1.
If the appointment is of type Estimate, the query needs to use the start_on field - and if the appointment is a GLA, the query needs to use the created_at field, as GLA's are not scheduled and don't have start_on values.
Right now, I'm querying the data using a Rails scope to filter down properties who've had their last appointment from and to a certain date like so (the following shows 'from'):
scope :last_appointment_from, ->(date, type) {
query = joins(:appointments)
query = query.where('appointments.start_on = (
SELECT MAX(appointments.start_on)
FROM appointments
WHERE appointments.property_id = properties.id)')
query = query.where('appointments.start_on >= ?', date)
query
}
But this only queries the start_on value.
I've tried looking into doing GREATEST(MAX(start_on), MAX(created_at)) - but then I'm not sure how to know which field to know to use in the where('events.start_on >= ?', date) part.
After typing this out, I thought of another possible workaround - to just create another database field that gets updated with the corresponding date on an active record callback based on what type of Appointment it is, called query_field or something (and run a script to set that value for all existing records) - and that way I can just query on that one field?
Any thoughts/help is greatly appreciated!
Since you already have a type field, it could be a use case for STI, i.e. same SQL schema for the model but different behavior on the ruby side.
Note the "type" field may already be causing issues with rails that you may not have considered as this field generally is reserved specifically for Single Table Inheritance STI in rails.
If you use STI you could just write an accessor that pulls the correct field from the database and presents it for each model.
I think this approach should work assuming that no appointment should have a created_at before its start_on unless it is GLA
scope :last_appointment_from, ->(date, type) {
query = joins(:appointments)
query = query.where('GREATEST(appointments.start_on, appointments.created_at) = (
SELECT GREATEST(MAX(start_on), MAX(created_at))
FROM appointments
WHERE appointments.property_id = properties.id)')
query = query.where('GREATEST(appointments.start_on, appointments.created_at) >= ?', date)
query
}
I'm not very good with Rails but for the pure MySQL you could use a where like this:
WHERE (
(appointments.created_at > date
AND appointments.type = 1)
OR
(appointments.start_on > date
AND appointments.type = 0)
)
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 :-)
The following query works fine in MySQL (which is generated by rails):
SELECT
sum(up_votes) total_up_votes
FROM
"answers"
WHERE
"answers"."user_id" = 100
ORDER BY
"answers"."id" ASC
Yet it gives the following error in Postgres:
PG::GroupingError: ERROR: column "answers.id" must appear in the GROUP BY clause or be used in an aggregate function
Edit: updated query. And here is the Rails model where this query is performed:
class User < MyModel
def top?
data = self.answers.select("sum(up_votes) total_up_votes").first
return (data.total_up_votes.present? && data.total_up_votes >= 10)
end
end
The query may execute in MySQL, but I doubt that it "works fine". It returns only one row, so the ordering is meaningless.
Your question is vague on what you actually want to do, but this should produce the same results as your query, in both databases:
SELECT sum(up_votes) as total_up_votes
FROM answers
WHERE user_id = 100;