Retrieve rows in which a column doesn't contain a value - mysql

I have a MySQL table like below:
| ID | userIDs
---------------
| 1 | 4,3,5
| 2 | 2,3
| 3 | 1,2,3
I want to retrieve all the rows in which userIDs doesn't contain 1.
I tried
SELECT * FROM tablename WHERE 1 NOT IN (userIDs)
But it's not working.

Use FIND_IN_SET
SELECT * FROM tablename
WHERE find_in_set(1, userIDs) = 0
But actually you should rather change your table design. Never store multiple values in a single column!

Related

MySQL string used in ORDER BY FIELD

I have an array of values stored in a single cell as a comma-separated string, thus:
"0,9,10,2,7,3,4,5,6,8,1,11,12"
I also have a table (table1) with a column (order) with these numbers in a different sequential order:
id|order
0 |5
1 |3
2 |4
3 |1
4 |2
etc
What I want to do is SELECT the "order" string from one table (table2) and use those values in an ORDER BY FIELD command when SELECTing from table1.
This should return row in this order: 3,4,1,2,0.
What I have so far is:
SELECT id
FROM table1
WHERE table1_id = 3746
ORDER BY FIELD(orderKey, (
SELECT `order` FROM table2
WHERE table2_id = 3746)
);
The problem seems to be that the SELECTorderFROM table2 is returned as a string which ORDER BY FIELD doesn't want to accept as input. It does SELECT the rows, but they are not in the specified order.
I have tried type-casting, but I may not have done this correctly. I also have sought an equivalent to a php explode function, to no avail.
MySQL version is 5.6.41
Any assistance is appreciated.
You can use FIND_IN_SET() in the ORDER BY clause:
select *
from table1
order by find_in_set(`order`, (select `order` from table2 where table2_id = 3746))
This will work if all the values in the column order of table1 exist in the string returned by the subquery as you mention in the question:
I also have a table (table1) with a column (order) with these
numbers in a different sequential order
.
See the demo.
Results:
| id | order |
| --- | ----- |
| 4 | 2 |
| 1 | 3 |
| 2 | 4 |
| 0 | 5 |
| 3 | 1 |

How to run alternative where condition if row is zero

Suppose i have a table
table
+-------------+
| id | name |
+-------------+
| 1 | xabx |
| 2 | abxd |
| 3 | axcd |
| 4 | azyx |
| 5 | atyl |
| 6 | aksd |
| 7 | baabc|
| 8 | aabcd|
+-------------+
first i have to get data if matches first some char like :
if name = aab
then have to run select * from table where name like 'aab%'
then it returns
+-------------+
| 8 | aabcd |
+-------------+
which execatlly i want
but if i have only abc
then the above query return 0 row
then i have to search from middle like :
select * from table where name like '%abc%'
then it returns which is the alternative
+-------------+
| 7 | baabc|
| 8 | aabcd|
+-------------+
i have no much knowledge about mysql is there any query which can do like if first where condition don't have row then run alternative where condition
i have tried this but didn't work as i want.
select * from table where name like 'abc%' or name like '%abc%'
fiddle
thanks in advance
This is somewhat your desired result:
select *from t
where (case
when name like 'abc' then 1
when name like 'bc%' then 1
when name like '%bc' then 1
when name like '%bc%' then 1
else null
end)
order by name
limit 1;
I just put all the combinations as conditions.
You can interchange their sequence or remove unnecessary condition.
limit 1 makes only 1 row visible for whichever condition satisfies.
Here is the answer from your fiddle. Check it out
Hope it helps!
This is a possible solution:
Left joining the table on itself, where the table is initially filtered by the more inclusive %bx% and then the join is filtered by the more restrictive bx%.
This allows you to use the joined name if it exists, but revert to the original if not:
SELECT t1.id, IF(t2.name IS NULL, t1.name, t2.name) name
FROM test t1
LEFT JOIN test t2 ON t2.id = t1.id AND t1.name like 'bx%'
WHERE t1.name LIKE '%bx%'
This may/may not be ideal depending on the size or your dataset.
COUNT checking may work
select *
from table
where name like 'aab%' or
((select count(*) from table where name like 'aab%') = 0 and name like '%abc%')
I guess that it would be a good idea to compute the count value into a variable first, however, the optimizer may recognize independent subquery anyway and run it once.

select statement from 2 unrelated tables

There's 2 unconnected tables, with no common IDs
+---------------------+
| names |
+------+--------------+
| name | lastN |
+-------------+-------+
| Anthony | monta |
| Ryo | shizu |
+------+--------------+
+----------------------+
| nicknames |
+------+---------------+
| nickname |
+------+---------------+
| miso_hungry |
+------+---------------+
I'm trying to run a select query on both tables and currently doing something like:
SELECT names.name, nicknames.nickname
FROM names, nicknames
WHERE names.name="miso_hungry" OR nicknames.nickname="miso_hungry"
I'm getting back a weird results with repeating identical rows, which doesn't make sense.
For example if I search for miso_hungry with the query above it will return every row of "names" table for some reason and append the correct rows from the "nicknames" table..
Attaching a screenshot of the results
Above should show "NULL" under name column, since "miso_hungry" is not found in that column and I'm not sure why it prints every row of the "names" table also.
You can use UNION Clause
Each SELECT statement within UNION must have the same number of columns
The columns must also have similar data types
The columns in each SELECT statement must also be in the same order
So we need to made them satisfy above condition. We can use Aliasing to do this.
SELECT name,(SELECT NULL) as nickname FROM names WHERE name = "miso_hungry"
UNION
SELECT (SELECT NULL) as name, nickname FROM nicknames WHERE nickname = "miso_hungry"
Edited
If you want to get the match count from both table use query like below :
SELECT SUM(count) as count FROM (
SELECT count(*) as count FROM names WHERE name = "miso_hungry"
UNION ALL
SELECT count(*) as count FROM nicknames WHERE nickname = "miso_hungry"
) both_table
The order of execution in your statement is from,where,select. With and implicit join you get a cartesian product which given
use sandbox;
create table n(name varchar(20));
create table nn(nickname varchar(20));
insert into n values('Antony'),('Ryo');
insert into nn values('miso');
results in
MariaDB [sandbox]> SELECT n.name, nn.nickname
-> FROM n, nn;
+--------+----------+
| name | nickname |
+--------+----------+
| Antony | miso |
| Ryo | miso |
+--------+----------+
2 rows in set (0.00 sec)
The where clause is then applied - which yields the same result.

How to create virtual column with multiple value using MySQL SELECT?

I can add virtual columns as
SELECT '1' as id
| id |
-------
| 1 |
But I want add multiple values, example:
SELECT ('1','2','3') as id
| id |
-------
| 1 |
| 2 |
| 3 |
But this don't work
Like Marc B said in a comment you can't have a single query split a single row into multiple rows, but you can have multiple queries, each producing one of the values, by chaining them together with union.
SELECT 1 id
UNION
SELECT 2
UNION
SELECT 3
As the answer was provided in a couple of comments I'll post it as a community wiki.

MySql SET intersection

I have next database
| ID | numbers |
|--------|------------|
| 1 | 1,2,3 |
| 2 | 4,5,6 |
| 3 | 2,3,4 |
To retrieve all rows where numbers holds a given number is easy:
SELECT * FROM mydb WHERE FIND_IN_SET(3, numbers)
This returns row 1 and 3
But now I want to pass an array/set of numbers and want to retrieve all entries where at least one number occurs in numbers, i.e. where the intersect of both sets is not empty
Something like:
SELECT * FROM mydb WHERE SET_INTERSECT('2,4', numbers)!=NULL
This should return all rows because every row holds 2 and/or 4.
The above doesn't work. Is this possible in mysql?
Thanks!
Why not use OR ?
SELECT * FROM mydb WHERE FIND_IN_SET(2, numbers) or FIND_IN_SET(4, numbers)
If you change the table structure to:
ID | NUMBERS
1 | 1
1 | 2
1 | 3
2 | 4
2 | 5
...
SELECT DISTINCT id FROM table WHERE numbers = 2 OR numbers = 4
/*or...*/
/*WHERE numbers IN (2, 4)*/