I am joining the tables Table_A and Table_B on columns Col_A and Col_B. Below are some test sample values.
Table_A, Col_A
USA1FullCover
USAMainland
USA2Islands
Table_B, Col_B
USA
USA1
USA2
When joining, I need to match the value 'USA' followed by a number exactly. For instance, the join result should look like this.
Col_A Col_B
USA1FullCover USA1
USAMainland USA
USA2Island USA2
I'm trying to achieve this in MySQL. I tried the rlike function. But the issue is that with rlike, I am not able to completely match them.
select
case when 'USA1FullCover' rlike 'USA' then 1 else 0 end;
#matches, but shouldn't
select
case when 'USA1FullCover' rlike 'USA1' then 1 else 0 end;
#matches, which is what I need/expect
select
case when 'USA1FullCover' rlike 'USA2' then 1 else 0 end;
#doesn't match, which is what I need/expect
My question is how can I fix the rlike so that the first case doesn't happen i.e. it doesn't match when there is no digit on the RHS? Or is it possible using regex? Taking a substring of the LHS doesn't help since we cannot really define the length beforehand.
Use
col_A regexp '^USA[0-9]{1}.+$'
to match USA followed by exactly one digit followed by any other characters.
To join only when such pattern exists
select a.*,b.*
from tableA a
join tableB b on
case when a.col_A regexp '^USA[0-9]{1}.+$' then substring(a.col_A,1,4) else '' end
= b.col_B
Related
i have a simple (i hope its simple) question.
In my database, i have an entry like this:
Now, i need a response with true or a count if the '514' in 'error_code' is in the string 'count_alarm'. In this example it returns zero because 514 isnt in count_alarm.
I beginns the query, but i dont know how i can solve this query:
select count(*) from table where sID='56df32a1463d4387' and [if
error_code in count_alarm then True]
Somebody an idea?
Perhaps you can just use REGEXP here:
SELECT COUNT(*) AS cnt
FROM yourTable
WHERE sID = '56df32a1463d4387' AND
count_alarm REGEXP CONCAT('[[:<:]]', error_code, '[[:>:]]');
find_in_set can parse comma separated fields:
select count(*)
from your_table
where sID = '56df32a1463d4387'
and find_in_set(error_code, replace(count_alarm, '|', ',')) > 0
or use instr
where sID = '56df32a1463d4387'
and instr(count_alarm, concat('|', error_code, '|')) > 0
select count(sID) as n514 from table where sID='56df32a1463d4387'
and count_alarm like '%|514|%'
The LIKE operator searches for the pattern |514| anywhere in the value under count_alarm.
The assumption is that the first and last character of that value is this character | else 514 would not be found if it is the first or last pattern within that value.
I need to find matching and non matching keywords from the database against user entered keywords.
Below is the database schema where we store all the known keywords
Table keywords
keyword varchar
Finding matching keywords in simple. We use following query to find matching keywords
select keyword from keywords where keyword in ('abc', 'pqr', 'xyz')
Where 'abc', 'pqr', 'xyz' are keywords supplied by the user.
However, I also need to find the keywords which are not present in the database. Definitely NOT IN does not work as it will return all the tags from the database rather than the one which was not matched. For example, if 'abc' and 'pqr' is present in the database and 'xyz' is not, I am expecting output as following
keyword present
abc 1
pqr 1
xyz 0
Please help me.
You can try below - using cte
with cte1 as
(
select 'abc' as key
union
select 'pqr' union select 'xyz'
)
select keyword,case when key is null then 0 else 1 end as is_present
from keywords left join cte1 on keyword=key
Select the three keywords and use a subquery to look them up in the keywords table:
select
keyword,
keyword in (select keyword from keywords) as present
from
(
select 'abc' as keyword
union all
select 'pqr' as keyword
union all
select 'xyz' as keyword
) user_keywords
order by keyword;
My database has 2 columns that contain text. When it has say 3 records as follows:
rec# col1 col2
1 my name is fred is
2 john mike
3 today not sat not it sat
I would appreciate help constructing a regular expression that will return record numbers:
1 -> because "is" matches
3 -> because "'not" and "sat" match (i.e. at least one match exists)
I think you can do this as:
select t.*
from table t
where col1 rlike replace(col2, ' ', '|');
This turns col2 into a regular expression. So, note that this answer will be very sensitive to the contents of col2. If it contains regular expression special characters, then this probably will not work.
What do you mean by "matches"?
This SELECT will find the rows where col1 contains at least one of the words is or not or sat:
SELECT rec_num
FROM tbl
WHERE col1 REGEXP '[[:<:]](is|not|sat)[[:>:]]';
This says that at least one of those words exists in both col1 and col2:
SELECT rec_num
FROM tbl
WHERE col1 REGEXP '[[:<:]](is|not|sat)[[:>:]]'
AND col2 REGEXP '[[:<:]](is|not|sat)[[:>:]]';
Change AND to OR to ask if one of the words exists in either (or both) column.
If you need the same word (is/not/sat) to match both col1 and col2, that is more complex:
SELECT rec_num
FROM tbl
WHERE ( col1 REGEXP '[[:<:]]is[[:>:]]'
AND col2 REGEXP '[[:<:]]is[[:>:]]' )
OR ( col1 REGEXP '[[:<:]]not[[:>:]]'
AND col2 REGEXP '[[:<:]]not[[:>:]]' )
OR ( col1 REGEXP '[[:<:]]sat[[:>:]]'
AND col2 REGEXP '[[:<:]]sat[[:>:]]' );
If you mean something else, practice asking precise questions.
Addenda
It is not practical in SQL to discover which words (if any) are in common between two text fields. Such a task would be better done in an application programming language (PHP, Java, Perl, ...).
I have got a filed in my database table which stores categories. I am storing the categories in the following format:
1,12,15
Now when I try to search for a product from category 1,
I use LIKE clause in my query such as
where (prod_catg LIKE %1,% or prod_catg LIKE %1% or prod_catg LIKE %,1% )
This returns me the products from all the three categories 1,12 and 15. Instead I just want the products from category 1.
I have also tried IN clause but no results found.
Can anyone please suggest me some other alternative.
prod_catg LIKE '1,%' --matches when 1 is the first category
OR prod_catg LIKE '%,1,%' --matches when 1 is somewhere in the middle
OR prod_catg LIKE '%,1' --matches 1 when is the last category
anyway you had better to refactor your schema by adding a category table and the reference to it on the product (main) table
EDIT
another way to face this problem is using REGEXP which will lead to a shorter WHERE clause (here is what i've used to test):
DECLARE #regexp VARCHAR(100);
SET #regexp = '^1,.*|.*,1$|.*,1,.*';
SELECT
'1,11,15,51,22,31' REGEXP #regexp AS test1,
'51,11,15,1,22,31' REGEXP #regexp AS test2,
'11,15,51,22,31,1' REGEXP #regexp AS test3,
'7,11,15,51,22,31' REGEXP #regexp AS test4,
'51,11,15,7,22,31' REGEXP #regexp AS test5,
'11,15,51,22,31,7' REGEXP #regexp AS test6;
this will match your prod_catg against the Regular Expression '^1,.*|.*,1$|.*,1,.*' returnig 1 (TRUE) if it matches, 0 (FALSE) otherwise.
Then your WHERE clause will look like:
WHERE prod_catg REGEXP '^1,.*|.*,1$|.*,1,.*'
explanation of regexp:
^1,.* --matches 1 at the beginning of a string followed by a `,` and any other char
.*,1$ --matches 1 at the end of a string preceded by a `,` and any other char
.*,1,.* --matches 1 between two `,` which are sourrounded by any other chars
| --is the OR operator
i'm sure this regexp could be much more compact but i'm not that good with regular expressions
obviuosly you can change the category you're looking for in the regular expression (try to replace 1 with 7 on the example above)
WHERE FIND_IN_SET('1', prod_catg)
You have a many to many relation between products and categories. You should create a new table to store the coresponding categories(cat_ids) for each product. You shouldn't have a column containing multiple category ids. This way your select would be much easier and a lot faster.
I have the following problem with a MySQL query in C#:
Given a list of strings, I want to query the database for any rows that match said strings. The strings are unique in that each string matches no more than one row. Today, my query looks something like this:
SELECT Id FROM SomeTable
WHERE SomeColumn IN("foo", "bar", "baz")
Now, ideally I would like to be able to map the result from the query directly to the list of strings I supplied in the IN clause:
String Returned ID
------------------------------------------
foo 123
bar NULL <-- Missing row filled with NULL
baz 42
This works fine as long as all strings I pass to the query match a row. When one is missing, however, I would like to fill in the blank with a NULL as in the example above.
Is there any way to accomplish this?
Edit: I should probably have pointed out that the solution must scale to a lot of strings. The way I do it right now is that I pass 100 at a time through the IN clause.
You could do this:
SELECT
helper.SomeColumn,
SomeTable.Id
FROM
(
SELECT 'foo' AS SomeColumn
UNION SELECT 'bar'
UNION SELECT 'baz'
) AS helper
LEFT JOIN SomeTable ON SomeTable.SomeColumn = helper.SomeColumn
Of course you can create the helper table (as a temp table) beforehand instead of inline.
Anyway, maybe it is smarter and more efficient to just do the query you have (WHERE SomeColumn IN (...)) and simply figure out the missing rows in your application. You will loop over them anyway, so you will notice.
What you could do is SELECT the set of strings as a result set and then LEFT JOIN on SomeTable.SomeColumn.
Try this:
SELECT Id
FROM (
SELECT "foo" SomeColumn
UNION ALL
SELECT "bar" AS SomeColumn
UNION ALL
SELECT "baz" AS SomeColumn
) b
LEFT JOIN
SomeTable a
ON a.SomeColumn = b.SomeColumn