When i use multiple like condition with AND keyword, it will return false value actually, it had value in table and my query as below:
SELECT * FROM tbl_student
WHERE name LIKE '%jame%'
AND ( id LIKE '%001%'
AND id2 LIKE '%002%'
)
This query return empty row
SELECT * FROM tbl_student
WHERE name LIKE '%jame%'
OR ( id LIKE '%001%'
AND id2 LIKE '%002%'
)
This query return data
tbl_student
Name ID ID2
jame 233 3234
jame333 1001 0222
jame333 Da 1001 1002
Why it is returned empty data when use AND keyword ?
Your query with the AND operator does not return the desired data, because your conditions placed within brackets always evaluate to false.
The reason this occurs is because you are trying to use LIKE '%str%' on an integer. This will not work expectedly. If you insist on using LIKE, you might want to CAST your integers to strings:
SELECT *
FROM tbl_student
WHERE name LIKE '%jame%'
AND (CAST(id AS CHAR) LIKE '%001%' AND
CAST(id2 AS CHAR) LIKE '%002%');
FYI, an e1 AND (e2 AND e3) logical expression remains the same with the brackets omitted.
Related
I have 2 MySQL tables that look like this:
first_table: the "json_field" values are just lists of integers, but the field type is "json":
id json_field
1 [1,2,3]
2 [2,3]
3 [1,3]
second_table: just a simple table with 2 fields (integer, varchar):
id name
1 bob
2 sam
3 mary
I need a single query that gives me all rows from first_table for which json_field values intersect with any "id" value from second_table that satisfies a simple query condition of "where name = 'sam'" (e.g. using a subquery)
Here's what I have so far:
select * from first_table where
JSON_OVERLAPS(json_field, (select group_concat(id) from second_table where name = 'sam'))
This query gives this error, however:
"Invalid JSON text in argument 1 to function json_overlaps: "The document root must not be followed by other values." at position 1."
I also tried this thinking that I had to convert the result of group_concat to json first, but got an SQL syntax error:
select * from first_table where
JSON_OVERLAPS(json_field, JSON_OBJECT(select group_concat(id) from second_table where name = 'sam'))
The correct result should give me the following 2 rows, since those rows contain id = 2, which is the id that corresponds to "sam" in second_table
1 1,2,3
2 2,3
Please assume that I must use a json field type for "first_table". The schema that I outlined above cannot be changed.
Don't use GROUP_CONCAT(), because it returns a string, not a set of rows. It can't be used to compare to a JSON document, and it can't be used to convert into a JSON array.
Instead, use JSON_ARRAYAGG() on a set of rows. This function transforms the set of rows into a JSON array.
select id, json_pretty(json_field) from first_table
where json_overlaps(json_field,
(select json_arrayagg(id) from second_table where name='Sam')
);
Demo: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=7a8d4f8a47042c1f9fa763c0689287ea
SELECT t1.id, CAST(t1.json_field AS CHAR), t2.id, t2.name
FROM t1
JOIN t2 ON JSON_OVERLAPS(t1.json_field, CAST(t2.id AS JSON))
WHERE t2.name = 'sam'
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=6d065e49643b04d4630f0031096aa4ee
There's a hard to understand issue with querying on a json field in MySQL. The data column is of type json.
The following query works perfectly fine
SELECT * FROM `someTable` WHERE data->'$.someData' in ('A')
However the following one returns nothing.
SELECT * FROM `someTable` WHERE data->'$.someData' in ('A','B')
Funnily enough this also works:
SELECT * FROM `someTable` WHERE data->'$.someData'='A' OR data->'$.someData'='B'
I'm clueless as to why this happens. I originally thought that WHERE x IN executed in a json query format might be doing something like && but even if the values are ('A','A') it still returns nothing which essentially shows that more than one value in WHERE x IN wont work.
SAMPLE DATA (any would do really)
id | data (json)
1 | {"someData":"A"}
2 | {"someData":"B"}
Too long for a comment...
This seems to be related to an optimisation MySQL is performing when there is only one value in the IN expression (probably converting it to an a = b expression) and then it ignoring quotes. Strictly speaking,
SELECT *
FROM `someTable`
WHERE data->'$.someData' in ('A')
or
SELECT *
FROM `someTable`
WHERE data->'$.someData' = 'A'
should return no data because
SELECT data->'$.someData'
FROM someTable;
returns
"A"
"B"
which is not the same as A. You need to use JSON_UNQUOTE (or if you have MySQL 5.7.13 or later the ->> operator) to get the actual value of the someData key:
SELECT JSON_UNQUOTE(data->'$.someData') FROm someTable;
SELECT data->>'$.someData' FROm someTable;
which gives
A
B
which then works fine with an IN expression:
SELECT *
FROM `someTable`
WHERE JSON_UNQUOTE(data->'$.someData') in ('A','B')
-- or use WHERE data->>'$.someData' in ('A','B')
Output:
id data
1 {"someData":"A"}
2 {"someData":"B"}
Demo on dbfiddle
You could try using a join on a subquery instead of a IN clause
SELECT *
FROM `someTable` s
INNER JOIN (
select 'A' col
union
select 'B'
) t ON t.col = s.data->'$.someData
I have an Access 2000 query that works on linked tables from SQL Server 2008 R2. I need to write it as a view or pass through query:
`
SELECT Max(CLng((Mid([tbl1]![ID],5)))) AS lastnumberused
FROM [tbl1]
WHERE ((([tbl1]![ID]) Like "OODD*" And ([tbl1]![ID]) Not Like "OODDid*" And ([tbl1]![ID]) Not Like "*x") AND ((CLng((Mid([tbl1]![ID],5))))<1000000));
`
So what I'm looking for is the max number under 1000000 that begins with OODD% but not OODDID%. Also the record cannot end with 'x'.
My code in TSQL for SQL Server looks like this and doesn't work...
`
SELECT
convert (int, (substring(tblMain.BarcodeID,5,10))) as X1, [ID]
FROM tblMain
WHERE ([tbl1]![ID] LIKE N'OODD%')
AND ([tbl1]![ID] NOT LIKE N'%x%')
AND ([tbl1]![ID] NOT LIKE N'OODDID%')
Select MAX (x1)+1
from bar1
where (x1<1000000)
`
suggestions?
thanks,H
Update 15june2013
WITH T1 (number)
AS
(SELECT substring(tbl1.ID,5,10)
FROM tblMain AS tbl1
WHERE (ID LIKE N'oodd%')
AND (ID NOT LIKE N'%x%')
AND (ID NOT LIKE N'ooddID%'))
SELECT (cast((number)as int)) FROM T1
This works and returns 561770 rows.
With T1(number)
as(SELECT cast(SUBSTRING(ID, 5, 7)as int)
FROM tblMain as tbl1
WHERE (tbl1.ID LIKE N'oodd%')
AND (tbl1.ID NOT LIKE N'%x%')
AND (tbl1.ID NOT LIKE N'%ooddID%')
AND ISNUMERIC(SUBSTRING(tbl1.ID,5,10))=1)
Select max(number) from T1
Also works but returns a number above 1000000
When a where statement is added the following code includes records that should have been excluded in the previous statement.
With T1(number)
as(SELECT cast(SUBSTRING(ID, 5, 7)as int)
FROM tblMain as tbl1
WHERE (tbl1.ID LIKE N'oodd%')
AND (tbl1.ID NOT LIKE N'%x%')
AND (tbl1.ID NOT LIKE N'%ooddID%')
AND ISNUMERIC(SUBSTRING(tbl1.ID,5,10))=1)
Select max(number) from T1
where x1 <1000000
The WHERE clause contains a [tbl1] table which is not present in the FROM clause. You should either change it to tblMainBee or add an "tbl1" alias in the FROM clause with AS.
Also, you have two unconnected SELECT statements, instead of a single one. Again, in the second SELECT, there is a bar1 table which doesn't appear anywhere else... is it correct?
Another error is that you cannot use "!" to separate table name and field name. You must use a dot.
Finally, there are issues when trying to convert the data type. You don't need it since comparison between strings also works.
Your access SELECT statement is much more straightforward.
Try with
WITH T1(number) AS (
SELECT substring(tbl1.ID,5,LEN(tbl1.ID)-4)
FROM tblMainBee as tbl1
WHERE ([tbl1].[ID] LIKE N'OODD%')
AND ([tbl1].[ID] NOT LIKE N'%x%')
AND ([tbl1].[ID] NOT LIKE N'OODDID%')
AND (IsNumeric(substring(tbl1.ID,5,LEN(tbl1.ID)-4)) = 1)
)
SELECT max(convert(bigint,number)) FROM T1 WHERE number < 1000000;
The second type conversion is implicit since 1000000 is numeric. The first one is necessary. Otherwise, it would consider '12346' bigger than '123421'.
Comparison between strings only works if they have fixed length.
Regards,
Try this
select MAX(CAST(SUBSTRING(ID,5,9) as INT))+1
from tblMainBee
where
ID Like 'OODD%'
AND ID Not Like 'OODDid%'
AND ID Not Like '%x'
AND ISNUMERIC(SUBSTRING(ID,5,9))=1
AND CAST(SUBSTRING(ID,5,9) as INT)<1000000
I have one table ABC with EMPLID, GRADE, SALARY and DATE as its fields.
I am executing the following 3 statements:
select count(*) from ABC;
Result :- 458
select count(*) from ABC where GRADE LIKE '%def%';
Result :- 0
select count(*) from ABC where GRADE NOT LIKE '%def%';
Result :- 428
My point here is: the result of second query plus the result of third query should be equal to the result of first query, shouldn't it?
Looks like you have 30 records where the GRADE is null.
null values are unknown, so do not match either condition.
Sql uses a three-valued logic: true, false &unknown. If you compare a NULL to any other value the result is unknown. NOT(unknown) is still unknown.
A WHERE clause only returns rows that evaluate to true. So the missing 30 rows in your example have a NULL in the Grade column.
Note that apart from the obvious case where you can have NULL values in your table (as others have mentioned), you could also have empty strings.
In Oracle:
-- Returns nothing
select 1 from dual where '' like '%'
In MySQL:
-- Returns 1
select 1 from dual where '' like '%'
Since you tagged your question with both oracle and mysql, you might be running into an incompatibility here, as in oracle '' IS NULL holds true!
Say I have the following table,
I would like to select the ratio of all the names that start with A to all the names that start with B
For example
Name
ABC
DEF
VVV
BBB
BCD
ZZZ
So the output would be 0.5. I want to call that output 'out'.
So the output should be
out
0.5
pretty much what I want is
Select count(*) from table where name like 'A%' / select count(*) from table where name like 'B%'
but in a single query.
You can do something like:
select
(select count(*) from table where name like 'a%') / (select count(*) from table where name like 'b%');
Here's a SQL Fiddle.
Note that if the divisor is zero, mySql will coalesce the zero into a null and the resulting value will be null. This is different than say, Oracle, which will throw a divisor is equal to zero exception.
Here's a SQL Fiddle showing this behavior, which you should probably trap and handle appropriately.
This query will do what you need:
SELECT ((SELECT COUNT(*) FROM `table` WHERE name LIKE 'A%') /
(SELECT COUNT(*) FROM `table` WHERE name LIKE 'B%')) AS `out`