Two ways to select ranges in SQL, only one in MongoDB? - mysql

I have the following SELECT statement for SQL.
SELECT TransAmount FROM STOCK WHERE TransAmount between 100 and 110;
However, this statement generates an error from querymongo.com. It says "Failure parsing MySQL query: Unable to parse WHERE clause due to unrecognized operator ". I assume it is talking about the between clause.
Correct me if I'm wrong, but does this SQL statement do the exact same thing as the one above?
SELECT TransAmount FROM STOCK WHERE TransAmount > 100 and TransAmount < 110;
This statement generates the following MongoDB code.
db.STOCK.find({
"TransAmount": {
"$gt": 100,
"$lt": 110
}
}, {
"TransAmount": 1
});
It looks like MongoDB doesn't have a 'between' operator. Does MongoDB handle selection within ranges with a different keyword, or do you have to set it up like so $gt/%lt?

Between is just a shortcut (a sort of symlink) to your second query, I guess it makes life easier.
MongoDB has not yet implemented such a shortcut, I have looked around a bit for a JIRA declaring someone wants such an operator however, no luck.
The one and only way of doing ranges in MongoDB is to use $gt and $lt (you could count $in etc but that is a different kind of range, not what your looking for).

Related

Change the output of the Knex rawquery

I am forced to use raw query with the Knex, since there is an issue with the union
One query, is not that bad. But now I have other type of issue.
All other Knex queries (non raw ones), they simply return an array with the results
For example:
knex('user_subscription_plan')
.select('*')
.where('paused_days', '>', 91)
.where('status', 'N_PAUSED')
will return an array, empty of there is no results.
However, if I run raw query, for example:
mySqlClient.raw('select * from user')
it will return an array, with two arrays inside it.
First one is the normal result, while other one contains some catalogue definitions.
That interferes with my logic. At the end of each call to knex, I have:
if (result.length > 0) {
// send email
}
Now, when I run the raw Query, the result is always greater then zero.
How can I tell Knex not to send the catalogue definitions, in other words, just send results back, exactly like it does on non raw queries?
According to https://github.com/knex/knex/issues/1802 there is no way around it, just do
mySqlClient.raw('select * from user')[0]
You should do it like #horatiu-jeflea answered.
Though we could add some way to knex to tell that also result of raw query should be parsed with default result parser. To make that way to appear in knex you could open feature request to its github issues.
Also there is https://knexjs.org/#Installation-post-process-response which you should be able to override to handle your raw query results are post processed.
If you want to get the same result as the select result, use select and pass your raw query as an argument without "SELECT" keyword. In your example, instead of doing:
mySqlClient.raw('select * from user')
You should do:
mySqlClient.select( mySqlClient.raw(' * from user') )

Multiple, unknown number of fields passed into a query

Is it possible to create a generic query that would work for different types of documents? For example I have "cases" and "factories",
They have different set of fields. e.g:
{
id: 'case_o1',
name: 'Case numero uno',
amount: 40
}
{
id: 'factory_002',
location: 'Venezuela',
workers: 200,
operating: true
}
Is it possible to create a generic query where I would pass the type of an entity (case or factory) and additional parameters and it would filter results based on those?
I could of course use javascript view, but it doesn't allow me to filter by multiple fields. Let's say I want to fetch all factories located in Venezuela, with number of workers between 20 and 55.
I started with this, but then I got stuck:
select * from `mybucket` as entity
where position(meta(entity).id, $entity_type) == 0
How do I pass multiple predicates and have the query to recognize them?
I can of course list fields like this:
where position(meta(entity).id, $entity_type) == 0
and entity.location == 'Venezuela'
and entity.workers > $workers_min
and entity.workers < $workers_max
but then
I'm gonna have to create a separate query for each entity
And even then it won't solve my problem - I have no idea how to ignore predicates, what if next time $workers_min and $workers_max are not passed, does it mean I have to create a query for every single predicate (column)?
For security reasons I cannot generate free-form queries and pass them to Couchbase server, all the queries are already stored in the database, our api just picks them up out of a document and executes them
I think it's possible to create a query that would be "short-circuiting" for args that's undefined (e.g. WHERE $location IS MISSING OR entity.location == $location or something like that)
Is it possible at all to create a query that would be able to effectively filter and order a dataset based on arbitrary parameters? Or there's no way?
#Agzam. Sorry. I were writting my comment when you said it. But anyway. What you are asking for is possible by using coalesces in a not too complex expressions, but it is a REALLY bad idea because this will drastically throw down most of internal database optimizations. Including the use of any existing index. So, except if you are dealing with a relatively small database (and you are sure it will remain being approximately the same size), I suggest you to better try distinct approach… This is, in fact, the reason I implmented sqlapi.
If you need to have all querys previously stored in database, it probably could be much better to sort given arguments by its name and precalculate and store precalculated querys for each possible combination.
You can do it by assigning a default value to the variable when is not used. For instance if $location is not used you can set it to -1 as default value.
Then the where condition would be:
WHERE ($location=-1 OR entity.location = $location)

nested "select " query in mysql

hi i am executing nested "select" query in mysql .
the query is
SELECT `btitle` FROM `backlog` WHERE `bid` in (SELECT `abacklog_id` FROM `asprint` WHERE `aid`=184 )
I am not getting expected answer by the above query. If I execute:
SELECT abacklog_id FROM asprint WHERE aid=184
separately
I will get abacklog_id as 42,43,44,45;
So if again I execute:
SELECT `btitle` FROM `backlog` WHERE `bid` in(42,43,44,45)
I will get btitle as scrum1 scrum2 scrum3 msoffice
But if I combine those queries I will get only scrum1 remaining 3 atitle will not get.
You Can Try As Like Following...
SELECT `age_backlog`.`ab_title` FROM `age_backlog` LEFT JOIN `age_sprint` ON `age_backlog`.`ab_id` = `age_sprint`.`as_backlog_id` WHERE `age_sprint`.`as_id` = 184
By using this query you will get result with loop . You will be able to get all result with same by place with comma separated by using IMPLODE function ..
May it will be helpful for you... If you get any error , Please inform me...
What you did is to store comma separated values in age_sprint.as_backlog_id, right?
Your query actually becomes
SELECT `ab_title` FROM `age_backlog` WHERE `ab_id` IN ('42,43,44,45')
Note the ' in the IN() function. You don't get separate numbers, you get one string.
Now, when you do
SELECT CAST('42,43,44,45' AS SIGNED)
which basically is the implicit cast MySQL does, the result is 42. That's why you just get scrum1 as result.
You can search for dozens of answers to this problem here on SO.
You should never ever store comma separated values in a database. It violates the first normal form. In most cases databases are in third normal form or BCNF or even higher. Lower normal forms are just used in some special cases to get the most performance, usually for reporting issues. Not for actually working with data. You want 1 row for every as_backlog_id.
Again, your primary goal should be to get a better database design, not to write some crazy functions to get each comma separated number out of the field.

How can i repeat MySQL's WHERE 1 query in MongoDB?

I can do this in MySQL:
WHERE 1 AND 1 AND 1
How can i repeat it in MongoDB? What is MongoDB's equivalent for WHERE 1 ?
UPDATE:
So. I don't know how choose best answer ^^ and expanded question. As #mark-hillick noticed - i'm searching the best way to build query.
Now I'm using this way (express+mongoose):
//req.query - get/post object in Express
for (var q in req.query) {
if (req.query[q]) { //simplified example
query[q] = req.query[q];
};
}
Collection.find(query)
Your suggestions?
There is a SQL-MongoDB Mapping Chart here that you will find useful.
It has a tonne of examples on what you do within MongoDB when you want to do the same operation as "WHERE" in MySQL. For example -
SELECT a,b FROM users WHERE age=33
is
db.users.find({age:33}, {a:1,b:1})
or
SELECT * FROM users WHERE a=1 and b=1
is
db.users.find({a:1,b:1})
MongoDB is document oriented database and documents in MongoDB consists key-value pairs. So, in MongoDB you can't run single value query as you did in MySql. Assuming you hold your data in the field name a, similar query in MongoDB could be like :
db.test.find({$and : [{a:1},{a:1}, {a:1}]});
If' you're trying to build query clauses, AND is implicit in Mongo. Therefore, if you have the following;
db.col.find({name:"dave"})
you could just add another;
db.col.find({name:"dave", age:33})
and so on.

Mysql is not counting the rows of dates from my php script

I am trying to count the number of dates that occur for a specific mem_id, however, my count output is always "0"... heres my code:
$datechecker = $postdate;
//$postdate is a date variable that is posted via a form into mysql, stored as a DATE
$sql = mysql_query("SELECT * FROM members WHERE mem_id='$id' AND postdate='$datechecker'");
$Counter = mysql_num_rows($sql);
if($Counter >= 0) {
echo "$datechecker $Counter";
exit();
}
This is the output I get: 2011-01-01 0
Even though I have about 10 occurrences of 2011-01-01, so why does my count say "0"? Can anyone help me solve this, or provide an alternate?
echo the string before you mysql_query it, this will validate if the query is what you expect it to be. You can also use count(*) within the query, instead of using php's mysql_num_rows()
I also hope that you're sanitising your input before you're querying that!
1) You didn't clean $postdate, who knows if it conforms to MySQL's definition of DATE?
2) You didn't show us how your members table looks like. Is mem_id primary key? If it is, then of course you're going to get 1 row out of it.
3) You aren't checking whether your query succeeds or not, you immediately pass the resource_id to the mysql_num_rows table - which is a wrong way to perform counting anyway because MySQL (like any other relational database) has inbuilt mechanisms of counting rows based on criteria.
My guess is that your query is failing, seeing there's not $id specified.