I've got an array of dates in a field called from. It can look something like this.
['2016-05-01', '2016-05-03', '2016-05-04']
I want to SELECT the last item (here 2016-05-04).
I've tried this:
SELECT `from`->"$[JSON_LENGTH(`from`) - 1]" FROM `table` WHERE `id` = 3;
but got that error:
ERROR 3143 (42000): Invalid JSON path expression. The error is around character position 2.
I've tried using a variable like this :
SET #count = (SELECT JSON_LENGTH(`from`) - 1 FROM `table` WHERE `id` = 3);
SELECT `from`->"$[#count]" FROM `table` WHERE `id` = 3;
but got the exact same error. But if I do:
SELECT `from`->"$[2]" FROM `table` WHERE `idx` = 3;
It works fine.
you can use :
SELECT JSON_EXTRACT(`from`,CONCAT("$[",JSON_LENGTH(`from`)-1,"]")) FROM `table`;
to get the last item in a json array.
MySQL 8 brings a very straight forward way to accomplish this:
select json_extract(json_array(1, 2, 3, 4, 5), '$[last]');
which returns
5
Can also do cool ranges, like everything but the last one:
select json_extract(json_array(1, 2, 3, 4, 5), '$[0 to last-1]');
which returns
[1, 2, 3, 4]
Related
I got the following table and I need to return 1 if all rows have disponibilidad = 1
The following QUERY works just fine, but i was looking for a more efficient way of doing it.
QUERY:
SELECT IF(AVG(disponibilidad) < 1, 0, 1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
RESULT:
As I see it, with an 'AND' it would be far more efficient, since it wouldn't have to do AVG().
MySql does not support a boolean AND aggregate function like Postgresql's bool_and.
Why not a simple MIN():
SELECT MIN(disponibilidad) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
This will return 1 only if all values of the column are 1 (provided the column is not nullable) and 0 if there is at least one row with 0.
How about something like
SELECT IF(COUNT(*)>0,0,1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1
AND disponibilidad <> 1
so that if there are any rows where disponibilidad is not 1, you output 0, otherwise if it's zero (so all disponibilidad values are 1) you output 1?
Lets say of I have this query SELECT * FROM table WHERE id IN (1,2,3,4);
In my current use case my ids are in an array like so [1,2,3,4]
How could I do the same query using the array data structure?
i.e. SELECT * FROM table WHERE id IN (myarray);
Edit: this is in ruby :)
Try this:
SELECT * FROM table WHERE id IN (myarray.map {|i| "\"#{i}\""}.join(", "));
You could convert the array to a comma separated string using the myarray.join(',') method.
The final code would look like this:
query = "SELECT * FROM table WHERE id IN (#{myarray.join(',')})"
You might run into some problems if the array values are strings, but it works just fine for integers.
User.where(id: [1, 2, 3, 4, nil]).to_sql
# SELECT "users".* FROM "users"
# WHERE ("users"."id" IN (1, 2, 3, 4) OR "users"."id" IS NULL)
or, if you can't/don't want to use where, you can drop into Arel to get just the IN string:
User.arel_table[:id].in([1,2,3,4]).to_sql
# => "users"."id" IN (1, 2, 3, 4)
though with this, you don't automatically get that nifty nil handling. If you don't have an ActiveRecord Model, but just using ActiveRecord::Base to execute queries in your database (as mentioned in the comments) you can do:
table = Arel::Table.new(:table) # :table is the name of the table in db
table[:id].in([1,2,3,4]).to_sql
# => "table"."id" IN (1, 2, 3, 4)
table.where(table[:id].in([1,2,3,4])).project(Arel.sql('*')).to_sql
# => SELECT * FROM "table" WHERE "table"."id" IN (1, 2, 3, 4)
And, avoiding Arel/ActiveRecord as much as possible, you can just do
ActiveRecord::Base.send(:sanitize_sql, ['id in (?)', [1,2,3,4]])
# => "id in (1,2,3,4)"
I'm trying to figure out why this query SELECTs just fine, but I can't use it to create a temporary table... The IF = '', 0 stuff didn't used to exist in the original query so I added it to make sure that I wasn't trying to sum anything that could potentially be an empty string, but it didn't fix the problem. This select works and returns the correct result set:
SELECT
SUM(((IF(reserve_transactions.Revenue = '',
0,
reserve_transactions.Revenue) * IF(reserve_transactions.Confidence = '',
0,
reserve_transactions.Confidence)) / 100)) AS rawadjusted
FROM
(store_locations
LEFT JOIN reserve_transactions ON ((store_locations.ID = location_sales)))
GROUP BY store_locations.Loc_Long
But this does not:
CREATE TEMPORARY TABLE tmptable_which_doesnt_work AS SELECT
SUM(((IF(reserve_transactions.Revenue = '',
0,
reserve_transactions.Revenue) * IF(reserve_transactions.Confidence = '',
0,
reserve_transactions.Confidence)) / 100)) AS rawadjusted
FROM
(store_locations
LEFT JOIN reserve_transactions ON ((store_locations.ID = location_sales)))
GROUP BY store_locations.Loc_Long
The error is: Error Code: 1292. Truncated incorrect DECIMAL value: ''
I have other queries where the situation is the same, actually. Sometimes with other truncated incorrect types. What am I missing here?
I think that the problem could be data and the logic of selecting only the numeric entries - You could try to define a functions as follows:
CREATE FUNCTION IsNumeric (sIn varchar(1024))
RETURNS tinyint
RETURN sIn REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
and apply it in the where clause for the two arguments, eventually trim unnecessary white spaces (as per How do I check to see if a value is an integer in MySQL? )
I have a table like this
The table in mysql
and I have a variable x in matlab
x=[1 5 6 8 10 21 99];
now I want to select like this
select * from tablename where key1 = x
I know mysql query must be string, and my variable x in matlab may be too long.
So how to do this in matlab? I failed in searching. Thanks
conn = database('instancename','username','password');
I know I can do this like
sql = 'select * from tablename where key in (1,5,6,8,10,21,99)'
The question is my x isn't constant and sometime could be a 1*N cell ( whose element is char), I want to put it into a script.
In SQL Server you write your query like this:
select * from tablename where key1 in {1, 5, 6, 8, 10, 21, 99}
I don't know about MY SQL but I imagine it is very similar. Which means all you need to do is convert x to the string '1, 5, 6, 8, 10, 21, 99' which you could do like this:
x_str = strjoin(cellstr(num2str(x'))',',')
and now the whole query becomes
query = sprintf('SELECT * FROM tablename WHERE key1 IN {%s}', x_str);
As an aside, another way to create x_str could be:
x_str = sprinft('%d, ', x);
x_str(end) = [];
I have this SQL statement:
SELECT * FROM `table` WHERE type = 3 OR type = 5 OR type = 4 and table.deleted = 1;
I've read that I can use parenthesis to accomplish this but I was wondering if then this would be valid:
SELECT * FROM `table` WHERE (type = 3 OR type = 5 OR type = 4) and table.deleted = 1;
OR
SELECT * FROM `table` WHERE (type = 3 OR type = 5) OR type = 4 and table.deleted = 1;
Both of these would be valid, but since AND has higher precedence than OR, they would mean different things:
Your first parenthesized query would pick deleted rows with types 3, 4, 5
Your second parenthesized query would select all rows with types 3, 5, in addition to deleted rows of type 4; this is the same meaning as in the original query without parentheses.
You can avoid the confusion altogether by using operator IN, like this:
SELECT * FROM `table` WHERE type IN (3, 4, 5) AND table.deleted = 1;
or if you wanted the second meaning
SELECT * FROM `table` WHERE type IN (3, 5) OR (type = 4 AND table.deleted = 1)
What you need is IN operator like
SELECT * FROM `table`
WHERE type IN ( 3, 5, 4) and deleted = 1;
AND has higher precedence than OR, so your first and third filters are equivalent to:
type = 3 OR type = 5 OR (type = 4 and table.deleted = 1)
Your second filter could equivalently be expressed using IN():
type IN (3, 5, 4) and table.deleted = 1