Subquery inside IN clause - mysql

I have the following query working:
SELECT DISTINCT table1.field1, table1.field2
FROM table1
WHERE table1.field3 IN (1,2,3)
Result:
field1 field2
Data1 60
Data2 61
Data3 62
And the following query only gives me the first row when it should give the exact same result as the first query.
SELECT DISTINCT table1.field1, table1.field2
FROM table1
WHERE table1.field3 IN (SELECT table2.field1 FROM table2 WHERE table2.field2 = 100)
Result:
field1 field2
Data1 60
If I execute the subquery (SELECT table2.field1 FROM table2 WHERE table2.field2 = 100), the result is "1,2,3", exactly like the first query.
What i'm I missing?

What you're missing is that a string with the value '1,2,3' is not a list of three integers. It's one string.
If you want x IN (SELECT y FROM z) to behave in the same way as x IN (1,2,3), then your sub-query must return three items, with the values 1, 2, and 3.
There are Split() functions on the web that take a string and return a record set consisting of multiple integers. And that may fix your problem.
But the fact that you have a single record with a single field holding multiple values is a sign of a deeper problem. You should never store multiple values in a relational database as a single string. Instead store multiple records, or multiple fields.

Related

How do select data with IF ELSE statement in a MySQL query

I get data from MySQL with if statement as code below. but I get an error:
Error Code: 1241. Operand should contain 1 column(s).
so can someone can help me?
I can not put it into the procedure, because I am using spring + mybatis in the project and i will put this code into them.
SELECT IF((SELECT COUNT(*) FROM table1 WHERE someField = 'A') < 0,
(SELECT * FROM table2 WHERE someField = 'A'),
(SELECT * FROM table1 WHERE someField = 'A'))
From the comments: I wanna get data of 1 in 2 tables when table 1 don't have data I will get data from table 2.
That sounds like union all and not exists:
select * from table1 where someField = 'A'
union all
select * from table2 where not exists(select 1 from tabe1 where someField = 'A'
Note that, for this to work, both tables must contain exactly the same number of columns, whith aligned datatypes. You should really be enumerating the columns that you want to show in the resultset in both unioned queries, to avoid any possible ambiguity. If needed, you can cast columns or add litteral values to any or both of the resultset to align the resultsets (without seeing your actual data structures, I cannot tell how to do).

MySQL Select enclosure

I have a code like this:
SELECT *
FROM table1
WHERE integer NOT IN (
SELECT varchars FROM table2 WHERE id = 1)
varchars consists of numbers separated by comma (1, 2, 3, 4 etc.) This code doesn't work correctly because the SELECT part between brackets gets enclosed by quotes ' ' and MySQL only reads the first integer before the first comma. How do I get read of those quotes or make that code work?
SELECT *
FROM table1
WHERE integer NOT IN (
SELECT varchars FROM table2 WHERE id = 1 FIELDS ENCLOSED BY 'NULL')
didn't help me either since it causes error #1064.
SELECT * FROM table1 LEFT JOIN table 2 ON FIND_IN_SET(integer,varchars) AND id =1 WHERE varchars IS NULL
This one is a correct answer mentioned by Mihai in the comment section above. Version of Sebas also works but when varchars for id = 1 in table2 doesnt exist it returns NULL while it should return all integer from table1 instead.
SELECT *
FROM table1 CROSS JOIN (SELECT varchars FROM table2 WHERE id = 1) AS t
WHERE NOT FIND_IN_SET(integer, t.varchars)
;
CROSS JOIN so the query is just executed on its own (as long as it returns a record)
FIND_IN_SET searches into a comma separated list of values.

mysql fallback WHERE statement

suppose I do this:
SELECT * FROM table WHERE field2 = '2019#162440' OR field2 LIKE '%%2019#%%';
In this case, it will try to execute the matching of BOTH field2 = '2019#162440'and field2 LIKE '%%2019#%%' conditions (ie, it will search for rows matching those conditions hence it takes some more computation power to try to find rows matching both condition even if it already found a row matching field2 = '2019#162440')
Is there a way to instruct mysql by reforming the query to ONLY try to execute field2 LIKE '%%2019#%%' if the condition field2 = '2019#162440' does not match anything so that the query becomes more efficient
IE. I essentially want mysql to only try to find rows matching field2 LIKE '%%2019#%%' only if no rows match field2 = '2019#162440'. If a row that matches field2 = '2019#162440' is found, do NOT try to match field2 LIKE '%%2019#%%'
Also, no subqueries
Let me start by stating that I am not an expert in MySQL. It is not nearly as optimized as some other DBMSes, so the following query might not actually reduce your execution time. But it's worth a shot...
If field2 is indexed, this might be a really fast solution:
-- Get results where field2 = '2019#162440'
SELECT *
FROM table
WHERE field2 = '2019#162440'
-- Append...
UNION
-- Get results where field2 LIKE '%%2019#%%' but only
-- if there are no rows where field2 = '2019#162440'
SELECT *
FROM table
WHERE NOT EXISTS(
SELECT *
FROM table
WHERE field2 = '2019#162440'
)
AND field2 LIKE '%%2019#%%'
You are going to run your fastest query and select all results. Then, append the second, slower query which contains an EXISTS. The EXISTS clause will return true if the subquery contains any rows, which should short-circuit the entire second query and prevent it from runnning (thus appending 0 rows). If the first query returns 0 rows, however, then the second query will kick in and run the slower LIKE comparisons.
The best I can do is use the FOUND_ROWS() function along with a UNION:
SELECT *
FROM t
WHERE field2 = '2019#162440'
UNION ALL
SELECT *
FROM t
WHERE FOUND_ROWS() = 0
AND field2 LIKE '%%2019#%%'
SQL Fiddle Demo

mySQL/SQlite subtractive query

I need a query in which it starts off by selecting the entire table, then there would be a few more querys that would remove entries from the first query. Ive accomplished this by using several querys and then comparing the results in my application. I was wondering if I can accomplish this in a single query.
Algorithm
Select All AccountIDs from table
Select AccountIDs from table where parameter1 = true
Remove those matches from the original query result
Select AccountIDs from table where parameter2 = true
Remove those matches from the remaining query result
and so on up to N parameters.
This would need to also be compatible with both mySQL and SQLite
I think you are looking for this:
SELECT AccountID FROM the_table
LEFT JOIN (
SELECT AccountID FROM the_table
WHERE
parameter1 = true OR
... OR
parameterN = true ;
) AS not_included USING (AccountID)
WHERE not_included.AccountID IS NULL -- only items with no match in the "not_included" sub-query
The not_included subquery returns all items for which any parameter is set to TRUE. You actually want to exclude these records from your final result set.
Then LEFT-JOIN the_table (i.e. all items) to this sub-result. The WHERE...IS NULL clause excludes items present in the_table but not present in not_included.
Therefore only items which you do not want to exclude remain in the final result set.
The most direct way to implement your algorithm is to use a compound SELECT statement:
SELECT AccountID FROM MyTable
EXCEPT
SELECT AccountID FROM MyTable WHERE parameter1 = 1
EXCEPT
SELECT AccountID FROM MyTable WHERE parameter2 = 1
However, this is also possible with a single WHERE expression:
SELECT AccountID
FROM MyTable
WHERE NOT (parameter1 = 1 OR
parameter2 = 1 OR
...)

How to check in mysql that normalized table is ok or not in mysql

MY base table have two colums assume col1,col2.
col1 have id, col2 have many comma seprated values colm1 is primary key.
like
col1 col2
---------------------
123 (22,34,12)
124 (45,67,11)
Now i have another table which is in normalized form of the first one like
col1 col2
---------------
123 22
123 34
123 12
124 45
124 67
Now the question is that i want to check that my second table have exect data of first table or not.
And if not then how to find that error.
( i need to show the extra row of second table and missing row of second table seperately )
Something liket that. But unverified
select col1, col2 from old_table
left outer join (select col1, group_concat(col2 separator ',') as col2
from new_table
group by col1) as new_table
on new_table.col1 = old_table.col1 and new_table.col2 = old_table.col2
Get a cursor or recordset and you will then do a loop of all records from table 1,
rs_col1 = id
rs_col2 = the comma seperated values
for each record in rs
select * from table_2 where id = rs_col1 and table_2.col2 not in (rs_col2)
loop
I think your unnormalized data is not quite useful, as the data is not ordered so you can't use a group_concat. However, you might be able to find a solution by using find_in_set and counting the amount of matches of col2 (normalized table) in col2 (unnormalized table) grouped by col1. You will then have to make sure that amount of matches is equal to the amount of elements in the multivalued cell.
Thanx to everbody for suggestions.
I got my solution through this query
select * table1 as a
join table2 as b
on a.col1=b.col1
where a.col2 not like concat('%',b.col2,'%')