Eddited to more accurate problem:
i have a table: id, supplierCode, propertyCode, specification. While doing search in products i would like to get products that specifications has a text like value1 and value2, so to get those products i would like an query sumething like this:
SELECT * FROM tbl WHERE (specification LIKE '%value1%' OR specification LIKE '%value2%') AND (those 2 got rows has the same supplierCode)
Or from other side of problem: Get all supplierCode's where whatever rows with same supplierCode has in the specification columns LIKE '%value1%' AND LIKE '%value2%'
Example:
id supplierCode propertyCode, specification
1 001234 11 i7-blabla
2 001234 13 15.3"
3 004321 15 i7-9761
4 004321 16 15.4"
5 003214 14 i7-15.3"
And if i'm searching for 'i7' and '15.3"' i could get 001234 and 003214 becouse they has i7 and 15.3" in their specifications
You can use the IN clause--definitely research thi problem a bit more, you would've definitely found a solution somewhere in the web.
SELECT * FROM tbl
WHERE specification IN ('value1', 'value2')
AND propertyCode = 'SOME_VALUE'
use LIKE instead of = sign
SELECT *
FROM tbl
WHERE (
specification LIKE CONCAT('%', value1, '%') OR
specification LIKE CONCAT('%', value2, '%')
) AND
propertyCode = valueHere
but if you are sure with the specification values use IN instead of OR (actually they are the same)
SELECT *
FROM tbl
WHERE specification IN ('value1','value2') AND
propertyCode = valueHere
you can use like keyword
pattern matching
SELECT * FROM tbl
WHERE (specification='%value1%' OR specification='%value2%')
group by propertyCode
$find = mysql_query("SELECT * FROM `tbl` WHERE (`specification` LIKE '%$value1%' OR `specification` LIKE '%$value2%') AND `propertyCode`='$propertycode'")or die(mysql_error());
$display = mysql_fetch_array($find);
Bare in mind you will need to change the PHP variables as you have not included any I have to presume you are looking for something like the above.
Also if you are looking to create a list then you will need to use a while statement on your fetch.
Related
(MySQL)
I have a query to check if 'phone_number' or 'fax_number' startsWith a value from a given array,
lets say const possibleValues = [123,432,645,234]
currently my query runs with the 'or' condition, to check if -
'phone_number' or 'fax_number' that starts with 123
or
'phone_number' or 'fax_number' that starts with 432
or
'phone_number' or 'fax_number' that starts with 645
or
'phone_number' or 'fax_number' that starts with 234
it runs extremely slow on a big database, and I wish to make it faster,
is there a way to make it run faster?
I'm kinda new to sql queries,
any help would be highly appreciated!
You can try something like:
SELECT * FROM table_1
WHERE CONCAT(',', `phone_number`, ',') REGEXP ',(123|432|645|234),'
OR CONCAT(',', `fax_number`, ',') REGEXP ',(123|432|645|234),';
Demo
Try creating an in-line table and join with it.
WITH telnostart(telnostart) AS (
SELECT '123'
UNION ALL SELECT '432'
UNION ALL SELECT '645'
UNION ALL SELECT '234'
)
SELECT
*
FROM your_search_table
JOIN telnostart ON (
LEFT(tel_number,3) = telnostart
OR LEFT(fax_number,3) = telnostart
you can use a case statement to add a flag column
select *
,case when left(phone_number,3) in (123,432,645,234) or left(fax_number,3) in (123,432,645,234) then 1 else 0 end as contact_check_flag
from table_name
As per your requirement, you can filter it or use it elsewhere.
SELECT * FROM table_1
WHERE `phone_number` REGEXP '^(123|432|645|234)'
OR `fax_number` REGEXP '^(123|432|645|234)';
But it won't be fast. (And no regular INDEX will help.)
If there phone numbers are spelled out like in the US: "123-456-7890", then you could use a FULLTEXT(phone_number, fax_number) index and
SELECT * FROM table_1
WHERE MATCH(phone_number, fax_number)
AGAINST('123 432 645 234');
This is likely to be much faster, but not as "general".
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
I have a following table
SNo Data
1 |AA|B|C|D|E|
2 |AB|B|C|D|
3 |AA|C|
4 |AA|
5 |AA|AB|AC|C|
6 |AB|B|C|
data is delimited by "|". I understand that the table is denormalized but I cannot change the schema.
The user will give one more more inputs. For example if the user gives input as AA and C I have to retrieve only those rows where only AA and C occurs and not other rows
In this case my output will be
SNo Data
3 |AA|C|
The query that I have tried
Select * from table1 where data like %AA%C% will retrieve rows 1,2,3,5,6
Thanks
Assuming that within a record:
"blank" values are not to be ignored—i.e. |AA||C| is not the same as |AA|C|; and
none of the values are repeated—i.e. |AA|C|AA| will never occur.
Then you can perform pattern matches and test the total value length:
SELECT SNo
FROM my_table
WHERE data LIKE CONCAT('%|', 'AA', '|%')
AND data LIKE CONCAT('%|', 'C' , '|%')
AND CHAR_LENGTH(data) = 1 + CHAR_LENGTH('AA')
+ 1 + CHAR_LENGTH('C' )
+ 1
See it on sqlfiddle.
You can use wildcards, but you have to separate the expressions like this:
SELECT * FROM table1
WHERE data LIKE '%|AA|%' AND data LIKE '%|C|%'
This gets you all the records that contain both |AA| and |C|. However, to limit to rows that match only both:
SELECT * FROM table1
WHERE data LIKE '%|AA|%' AND data LIKE '%|C|%'
AND LENGTH(data) = 6
If you have just two, you may as well key them in and actually use an index on the data column though:
SELECT * FROM table1
WHERE data = '|AA|C|' OR data = '|C|AA|'
Which on older versions of MySQL can be optimized to:
SELECT * FROM table1
WHERE data = '|AA|C|'
UNION ALL
SELECT * FROM table1
WHERE data = '|C|AA|'
Alternatively, you could use a regular expression, which would not utilize an index.
A little idea using regular expressions:
select * from table1 where data regexp '(\\|AA\\|)+.*(\\|C\\|)+';
If I have understood correctly, what you are asking is "get the rows which matches input with delimiter".
So if input is "AA" and "c" then get rows where Data column will have result exactly like
|AA|C|
You can probably do like
select * from table1 where data = select concat('|',concat_ws('|','AA','C'),'|')
$whereClause = array();
foreach( $input AS $search ){
$whereClause[] = sprintf("data REGEXP '|?%s|?'", $search);
}
$sql = "SELECT * FROM tbl WHERE ".implode(" AND ", $whereClause);
Regular Expression Explained
This is the regular expression '|%s|' .
I have a field ('roles') with this values
roles
row_1: 1,2,3,5
row_2: 2,13
I do this:
SELECT * FROM bloques WHERE 2 IN (roles)
and only find row_2, because it starts by 2
The LIKE option doesn't work because if I find 1
SELECT * FROM bloques WHERE roles LIKE '%1%'
, it gives me both rows.
FIND_IN_SET function cal helps you:
SELECT FIND_IN_SET('b','a,b,c,d');
For your code:
SELECT * FROM bloques WHERE FIND_IN_SET(2,roles);
Also, I suggesto to you that move your schema to 1NF
Could you use REGEXP? http://dev.mysql.com/doc/refman/5.1/en/regexp.html
Otherwise, you could add commas to the front and end of your rows.
select * from mytable where ',' + roles + ',' like '%,2,%'
SELECT
*
FROM
bloques
WHERE
roles LIKE '%,2,%'
OR roles LIKE '2,%'
OR roles LIKE '%,2'
The first case will give you all cases where 2 is in the middle of a set, the second case is when 2 starts the set, and the third case is when 2 ends the set. This is probably terribly inefficient, but it should work.
You can use this regex here:
SELECT * FROM bloques
WHERE roles REGEXP '[[:<:]]2[[:>:]]';
... or, in more generic case:
SELECT * FROM bloques
WHERE roles REGEXP CONCAT('[[:<:]]', :your_value, '[[:>:]]');
You need to use these weird-looking things, as they match word boundaries - preventing match for '2' to occur at '23' and '32'. )
The problem is that query is only the beginning of the troubles caused by using denormalized field. I'd suggest using either SET type (if the number of options is limited and low) or, way better, junction table to store the m-n relationships.
Use FIND_IN_SET() function
Try this:
SELECT * FROM bloques WHERE FIND_IN_SET(1, roles);
OR
SELECT * FROM bloques
WHERE CONCAT(',', roles, ',') LIKE '%,1,%';
How would I go about doing something like:
SELECT * FROM mytable
WHERE people IN ('Jack', '%Bob%')
Finding all fields that either equal 'Jack' or contain 'Bob'? I don't think my example is the proper syntax because it's not pulling up any records.
Simply :
SELECT * FROM mytable WHERE people='Jack' OR PEOPLE LIKE '%Bob%'