how to select from mysql table from matlab variable (array/cell) - 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) = [];

Related

Take substring and use it in multiple where condition in sql

I have a string which has some values concatenated. Like 'Val1val2val3val4'.
I have a query like
Select * from table where var1 = Val1 and var2 = val2 and var3 = var3;
Val1 and val2 are length only 4 but val3 may differ in length. Val4 is of length 8 and no use.
I can form query with functions like var1 = substring (text, 1, 4), var2 = substring (text, 5, 8) and for var3 = substring (text, 9, Len(text) - 8).
But the problem is, i have to manually edit replace the value in 3 places in query each time in workbench. Which is a painful task in my case. Is it possible to just put the string in one place and make the SQL automatically take substrings and use in where clause conditions? I have only read access, cannot modify tables. Local variables like #var = Text, throws error code 1046. Hands tied for me. Need ideas if feasible.
You could put the input string into a derived table of one row, and cross-join that to your table:
SELECT ...
FROM (SELECT 'Val1val2val3val4' AS text) AS v
CROSS JOIN MyTable
WHERE var1 = substring(v.text, 1, 4) AND ...
Or you could use a user-defined variable and use it in a subsequent query:
SET #var = 'Val1val2val3val4';
SELECT ...
FROM MyTable
WHERE var1 = substring(#var, 1, 4) AND ...
You mentioned you got a 1046 error, but it's not clear how you were trying to assign it, so I can't guess what happened.
If you are sure that both #var1 and #var2 have length of 4 chars, then all you need is:
WHERE text LIKE CONCAT(#var1, #var2, #var3, REPEAT('_', 8))
If not then:
WHERE text LIKE CONCAT(#var1, #var2, #var3, REPEAT('_', 8))
AND CHAR_LENGTH(#var1) = 4
AND CHAR_LENGTH(#var2) = 4;
If the comparison should be case sensitive, change to:
WHERE text LIKE BINARY CONCAT(#var1, #var2, #var3, REPEAT('_', 8))

Pop the last item in a JSON Array in MySQL 5.7

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]

How to run concurring SQL query?

I am trying to run this sql query.
SELECT * FROM AverageFeedInfo WHERE No = (
SELECT No FROM UserResponse2 where Not Complain = '' )
When I run SELECT No FROM UserResponse2 where Not Complain = '' individually I have result 2 and 6, but if I run this
SELECT * FROM AverageFeedInfo WHERE No = (
SELECT No FROM UserResponse2 where Not Complain = '' )
I have only the result for 2 not for 6. Is it possible to get the answer for both 2 and 6. To be more clear is it possible to run the sql query like
SELECT * FROM AverageFeedInfo WHERE No = 2 or No = 6
Generally, when checking set membership in a SQL-based context use of an IN operator is more appropriate than =.

How can I combine ANDs and ORs in my SQL statement

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

SQL Server 2008: Error converting data type nvarchar to float

Presently troubleshooting a problem where running this SQL query:
UPDATE tblBenchmarkData
SET OriginalValue = DataValue, OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
WHERE
FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID FROM tblZEGCode
WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Results in the following error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to float.
The really odd thing is, if I change the UPDATE to SELECT to inspect the values that are retrieved are numerical values:
SELECT DataValue
FROM tblBenchmarkData
WHERE FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID
FROM tblZEGCode WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Here are the results:
DataValue
2285260
1205310
Would like to use TRY_PARSE or something like that; however, we are running on SQL Server 2008 rather than SQL Server 2012. Does anyone have any suggestions? TIA.
It would be helpful to see the schema definition of tblBenchmarkData, but you could try using ISNUMERIC in your query. Something like:
SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335
ELSE 0 END
Order of execution not always matches one's expectations.
If you set a where clause, it generally does not mean the calculations in the select list will only be applied to the rows that match that where. SQL Server may easily decide to do a bulk calculation and then filter out unwanted rows.
That said, you can easily write try_parse yourself:
create function dbo.try_parse(#v nvarchar(30))
returns float
with schemabinding, returns null on null input
as
begin
if isnumeric(#v) = 1
return cast(#v as float);
return null;
end;
So starting with your update query that's giving an error (please forgive me for rewriting it for my own clarity):
UPDATE B
SET
OriginalValue = DataValue,
OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
I think you'll find that a SELECT statement with exactly the same expressions will give the same error:
SELECT
OriginalValue,
DataValue NewOriginalValue,
OriginalUnitID,
DataUnitID OriginalUnitID,
DataValue,
CAST(DataValue AS float) * 1.335 NewDataValue
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
This should show you the rows that can't convert:
SELECT
B.*
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
AND IsNumeric(DataValue) = 0
-- AND IsNumeric(DataValue + 'E0') = 0 -- try this if the prior doesn't work
The trick in the last commented line is to tack on things to the string to force only valid numbers to be numeric. For example, if you wanted only integers, IsNumeric(DataValue + '.0E0') = 0 would show you those that aren't.