Query for a set with multiple options - mysql

I have a table with a SET-field where several of the options can be selected. I want to select all rows where at least one of the options I specify is set.
The options are: A, B, C and D
Row 1: A,B
Row 2: A,C
Row 3: C
Row 4: D
I specify A and C, so the rows returned should be 1, 2 and 3
Any ideas?

You could use FIND_IN_SET, you could use LIKE:
With FIND_IN_SET, you would do something like:
SELECT * FROM myTable WHERE FIND_IN_SET('A', set_column_name)>0;
Read more about FIND_IN_SET here.
Live DEMO with the above.
With LIKE
SELECT * FROM myTable WHERE set_column_name LIKE '%A%';
This will search the entire column for the specified letter.
Read more about LIKE here.
Live DEMO with the above.
You can also use set_column_name = 'A' for single exact entries

Related

Select row where id in array of mysql row

So I have an database where I have a string in each row eg: 1,4,56,3,23
I want to find every row where say 1 is in it, so this row would be found a 1 is at the start but if I have 4,1,54,32,2 it wont find it.
This is the code I'm using:
WHERE ".$id." IN ( outcomes )
You can use LIKE because you have a string separated by comma.
SELECT * FROM users WHERE outcome LIKE '41,%' OR outcome LIKE '%,41,%' OR outcome LIKE '%,41';
The above code select users which have outcome 41 in the list.
Use FIND_IN_SET :
SELECT *
FROM table
where FIND_IN_SET(".$id.",outcomes);
You can use the INSTR function as well :
SELECT *
FROM table
WHERE INSTR(".$id.",'1') > 0

SQL show results for A column first then show results for B column

I want SQL to show / order the results for the column name first then show results for the description column last.
Current SQL query:
SELECT * FROM products WHERE (name LIKE '%$search_query%' OR description LIKE '%$search_query%')
I tried adding order by name, description [ASC|DESC] on the end but that didn't work.
It's for optimizing the search results. If a certain word is found in description it should go last if a certain word is also found in the name column.
You can use a CASE statement in an ORDER BY to prioritize name. In the example below all results where name is matched will come first because the CASE statement will evaluate to 1 whereas all other results will evaluate to 2.
I'm not sure by your problem description what exactly you want the behavior to be, but you can certainly use this technique to create more refined cases to prioritize your results.
SELECT *
FROM products
WHERE (name LIKE '%$search_query%' OR description LIKE '%$search_query%')
ORDER BY CASE WHEN name LIKE '%$search_query%' THEN 1 ELSE 2 END
If you want the names first, the simplest order by is:
order by (name like '%$search_query%') desc
MySQL treats booleans as numbers in a numeric context, with "1" for true and "0" for false.
While this is undocumented, when results sets combined by a UNION ALL and not sorted afterwards, they stay in the order returned, as UNION ALL just adds new results to the bottom of the result set. This should work for you:
SELECT * FROM products
WHERE name LIKE '%$search_query%'
UNION ALL
SELECT * FROM products
WHERE (description LIKE '%$search_query%' AND name NOT LIKE '%$search_query%')

MySQL - WHERE x IN ( column)

I tried something out. Here is a simple example in SQL Fiddle: Example
There is a column someNumbers (comma-seperated numbers) and I tried to get all the rows where this column contains a specific number. Problem is, the result only contains rows where someNumbers starts with the specific number.
The query SELECT * FROM myTable where 2 in ( someNumbers ) only returns the row with id 2 and not the row with id 1.
Any suggestions? Thank you all.
You are storing data in the wrong format! You should not be storing multiple values in a single string column. You should not be storing numbers as strings. Instead, you should have a junction table with one row per id and per number.
Sometimes, you just have no choice, because someone else created a really poorly designed database. For these situations, MySQL has the function find_in_set():
SELECT *
FROM myTable
WHERE find_in_set(2, someNumbers ) > 0;
The right solution, however, is to fix the data model.
While Gordon's answer is a good one, here is a way to do this with like
SELECT * FROM myTable where someNumbers like '2,%' or someNumbers like '%,2,%' or someNumbers like '%,2'
The first like checks if your array starts with the number you are looking for (2). The second one checks if 2 is within the array and the last like tests for appearance at the end.
Note that the commas are essential here, because something like '%2%' would also match ...,123,...
EDIT: As suggested by the OP it may happen that only a single value is present in the row. Consequently, the query must check this case by doing ... someNumbers = '2'
I would suggest this query :
SELECT * FROM myTable where someNumbers like '%2%'
It will select every entry where someNumbers contains '2'
Select * from table_name where coloumn_name IN(value,value,value)
you can use it

Nested select statement in mysql -my code doesn't work

here is my query
SELECT con_serial,column2,column3
FROM
(SELECT con_serial,column2,column3
FROM big_table
WHERE ISNULL(contact1, '')+'#'+ISNULL(contact2, '')+'#'+ISNULL(contact3, '')+'#'+ISNULL(contact4, '')+'#'+ISNULL(contact5, '')
LIKE '%' + '".$conserial."' + '%') AS a
WHERE con_serial
IN('".$contact1."','".$contact2."','".$contact3."','".$contact4."','".$contact5."')
at the inner select i wish to get the rows which have this value $conserial in one of their 5 columns(contact1...contact5)
and the outer select to choose the rows from it that their column con_serial is one of the variables ($contact1...$contact5)
can anybody see what's wrong here?
Despite your new formulation, it remains very much unclear.
Nevertheless I'll try to give you an answer, based on what I can guess...
First here is how I'd reformulate your need:
you have some values in PHP variables: one $conserial and five $contact# where # is 1-5
the table structure contains at least these columns: con_serial, column2, column3, and five contact# where # is 1-5
you want to select rows where both (here is the most strange part of your need):
at least one of the contact# columns matches the PHP $conserial value
the con_serial column matches at least one of the PHP $contact# values
That said, note that you don't need to have two nested SELECT: you only want each row to satisfy two conditions, so they can be ANDed in the WHERE clause.
Based on that, your query should be:
$query = "
SELECT con_serial, column2, column3
FROM big_table
WHERE con_serial IN ('$contact1', '$contact2', '$contact3', '$contact4', '$contact5')
AND '$con_serial' IN (contact1, contact2, contact3, contact4, contact5)
";
i guess the sum part in where clause is nut allowed
any way i've solved this with using two IN like this
SELECT con_serial,,column2,column3
FROM(SELECT con_serial,column2,column3
FROM
big_table
WHERE '".$conserial."' IN(contact1,contact2,contact3,contact4,contact5)) a
WHERE con_serial IN('".$contact1."','".$contact2."','".$contact3."','".$contact4."','".$contact5."'
this was wat i wanted Tnx any way ;)

mysql: special use of concat

I have table A and B with many to one associations (b contains fk_a). Let's assume the sample tables are as follows:
A:
id first
1 sample
2 sample
B:
id fk_a type value
1 1 som thing
2 1 oth other
3 2 som thing
4 2 oth any
I would like the "first" column in table A to be unique, and I would like to achieve it by having to:
desired A:
id first
1 sample-thing-other
2 sample-thing-any
Is it possible to use pure MYSQL to use UPDATE and CONCAT on table A to obtain desired update?
It would be easy if I had everything in one table, I could just write
UPDATE A
SET first = CONCAT(first, value)
but unfortunately I have many-to-one association and I am not sure if it is even possible in such case.
I do not have the instance of mysql, and not test it. use the group_concat
UPDATE A, (SELECT fk_a, GROUP_CONCAT(value SEPARATOR '-') as concat_value FROM B GROUP BY fk_a) AS t
SET A.first = CONCAT(A.first, '-', t.concat_value)
WHERE A.id = t.fk_a;
Group_Concat is your friend.
But may I remind you of first normal form?