SQL query 'where clause' for matching strings - mysql

Use-Case: I want to select all entries from table t123, where field 'text' of the table is NOT a subset string of 'text_target'.
For example:
text_target = 'abf'
t123 has entries like,
name text
1) record1 abc
2) record2 abd
3) record3 af
result should be records 1 and 2, since their 'text' field is not subset of text_target value 'abf'.
EDIT: corrected the question

use like
select * from t123 where text like'ab%'

I think you'll need to explode the string:
where ( (test like '%a%') +
(test like '%b%') +
(test like '%f%')
) <> length(test)
It is not obvious that even regular expressions can help.
However, looking at strings as sets with one element per letter sounds like a data modeling problem. You may want to ask another question describing your data and suggestions on how you might design your database.
Here is a rextester (thanks to Tim).

Not elegant, but I suppose:
select *
from t123
where not ( substring( text from 1 for 1 ) in ( 'a', 'b', 'f', ' ' )
and substring( text from 2 for 1 ) in ( 'a', 'b', 'f', ' ' )
and substring( text from 3 for 1 ) in ( 'a', 'b', 'f', ' ' ) )
could return those rows that contain other letters.

Use regular expression. For instance, if we suppose that you want to retrieve records NOT containing characters from "text_target" ("abf") :
SELECT * FROM t123 WHERE NOT text RLIKE "a|b|f"

Related

How to get rows which contains unknown values in SET column?

Database is MySQL 5.6
CREATE TABLE set_t
(
set_r SET ('a', 'b', 'c')
);
INSERT INTO set_t (set_r) VALUES ('a,b,c'), ('a,b');
In my case i know only 'a' and 'b'.
For example, need to select row where set_r is "a,b,c".
Value 'c' is unknown, cant use it in query.
Values order is unknown also. They are may be set_r SET ('c', 'b', 'a') or else.
How to select rows, which contains unknown values?
The easy way to do it for your sample data is with NOT IN:
SELECT *
FROM set_t
WHERE set_r NOT IN ('a', 'b', 'a,b')
But this does not scale well if you have larger set and you want to include more members than a and b in the list of known members.
Every member of a set is stored as a numeric value.
In your set the numeric values are:
SET Member Decimal Value Binary Value
'a' 1 001
'b' 2 010
'c' 4 100
So, a value like 'a,b' is stored as 3 (Binary 011)
and a value like 'a,b,c' is stored as 7 (Binary 111)
If you know the numeric values of the known members, which you can get by the order they are defined in the set, then you can use bit operations to get what you want:
SELECT *
FROM set_t
WHERE set_r | 3 <> 3 -- 3 is the numeric value of 'a,b'
or:
SELECT *
FROM set_t
WHERE set_r | 0b11 <> 0b11 -- 0b11 is the numeric binary value of 'a,b'
See the demo.
You can use find_in_set() to check for individual values. See SET documentation here
select * from set_t where find_in_set('a', set_r) and find_in_set('b', set_r)
This gives you
set_r
(a,b,c)
(a,b)
See this db<>fiddle
If you don't want the second row, you can add and not like 'a,b'.
The most efficient method is to use the binary comparisons. This assumes that you know the position of 'a' and 'b' in the set:
select *
from set_t
where (set_r | b'11') <> b'11';
You can also do this using string operations. This is a bit of a pain, because you need to handle the comma delimiter:
select *
from set_t
where replace(replace(replace(concat(',', set_r, ','), ',a,', ','), ',b,', ','), ',', '') <> ''
The logic is:
Put delimiters at the beginning and end of set_r.
Remove delimited elements, replacing them with the delimiter.
Check if the result only has delimiters.
This version works regardless of the size of the set and the position of the elements you want to compare against.
Here is a db<>fiddle.

Count Characters after a certain pattern

I have a database that contains a column "Code" where the records have the following format "xx-xxx" and "xx-xx", for the later format i want to add a zero after the "-" to make it "xx-0xx", is there anyway to count the characters after a certain pattern in Mysql
Hmmm. If those are your only two possibilities, you can use case:
select (case when length(code) = 5
then replace(code, '-', '-0')
else code
end) as new_code
If you want to be more general, deconstruct the string and build it back again:
select concat_ws('-', substring_index(code, '-', 1),
lpad(substring_index(code, '-', -1), 3, '0')
)
Yes, you can use the CHAR_LENGTH(str) like this:
SELECT code,CHAR_LENGTH(SUBSTR(code,3))
from table

MySQL How to split string from column by " " and insert result separated by , into another column?

I would like to ask how to split string from column (all rows in table) by " " and insert result separated by , into another column in same table?
Many thanks for any advice.
Table struct example:
------------------------------------------
| Original string | Spliced string |
------------------------------------------
| Some string 001 | Some,String,001 |
------------------------------------------
If I needed to "split" a string on a delimiter, I'd likely make use of the nifty SUBSTRING_INDEX function. But there are a few quirks to be aware of.
The approach I would take would certainly be to write a SELECT statement first. That would include the expression(s) in the SELECT list that return the "separated" values that I wanted to assign to another column. I'd get those expressions tested using a SELECT statement, before I wrote an UPDATE statement.
SELECT t.id
, t.column_i_want_to_split
, expr1
FROM mytable t
ORDER BY t.id
To test specific cases, I'd make use of an inline view
SELECT t.id
, t.note
, t.val
, expr1
FROM ( SELECT 1 AS id, 'empty string test' AS note, '' AS val
UNION ALL SELECT 2, 'null', NULL
UNION ALL SELECT 3, 'one space', ' '
UNION ALL SELECT 4, 'four spaces', ' '
UNION ALL SELECT 5, 'test5', ' abc def '
UNION ALL SELECT 6, 'test6', 'g hi kl m'
) t
ORDER BY t.id
Once I had the expression(s) returning the values I want to assign to another column, I'd convert the SELECT into an UPDATE statement. To process all rows, omit the WHERE clause.
UPDATE mytable t
SET t.another_column = expr1
Without a more definitive specification, or at least some concrete examples of what you are attempting to achieve, we're just guessing. Given only a general description of the problem, all we can offer is some general advice.

Grab a number in between a varchar in SQL

I am trying to grab a number by using SQL query. I need to grab the number before it says 'LEADS'
Sample of entry I might encounter:
PDIP300MIL-14LEADS
QFN6X6-40LEADS
QFN6X6-240LEADS
WSOIC/16LEADS
So as you can see the prefix can be any length. Also sometimes the delimeter is / or -. But it is fix that the suffix is LEADS.
On a sidenote. Other entries are like ICL7665 BCSA so it has no leads so it has to be skipped.
Edit: I am very sorry if I am not that clear. The one I am trying to grab is the number between the delimeter and Leads.
So in the four examples I am trying to grab: 14, 40, 240, 16.
You can do something like using substring_index
select
substring_index(
substring_index(
replace(col,'/','-')
,'LEADS'
,1),
'-'
,-1
)
from table1
DEMO
To skip entries you can filter result by using having clause
select
substring_index(
substring_index(
replace(col,'/','-')
,'LEADS'
,1),
'-'
,-1
) num
from table1
having num * 1 > 0
DEMO 2
https://dev.mysql.com/doc/refman/5.1/en/regexp.html
SELECT * FROM table WHERE field REGEXP '[0-9]+LEADS$'

How to export all words from sql table or sql database

Let's say we have following table.
UserId | Message
-------|-------------
1 | Hi, have a nice day
2 | Hi, I had a nice day
I need to have all { Hi,-have-a-nice-day-I-had } words separately.
Is there any way to do that ? What if I want to export words from whole database tables ?
Similar results would be also good.
try this:In Sql server 2005 or above
create table yourtable(RowID int, Layout varchar(200))
INSERT yourtable VALUES (1,'hello,world,welcome,to,tsql')
INSERT yourtable VALUES (2,'welcome,to,stackoverflow')
;WITH SplitSting AS
(
SELECT
RowID,LEFT(Layout,CHARINDEX(',',Layout)-1) AS Part
,RIGHT(Layout,LEN(Layout)-CHARINDEX(',',Layout)) AS Remainder
FROM YourTable
WHERE Layout IS NOT NULL AND CHARINDEX(',',Layout)>0
UNION ALL
SELECT
RowID,LEFT(Remainder,CHARINDEX(',',Remainder)-1)
,RIGHT(Remainder,LEN(Remainder)-CHARINDEX(',',Remainder))
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)>0
UNION ALL
SELECT
RowID,Remainder,null
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)=0
)
SELECT part FROM SplitSting ORDER BY RowID
SQLFIDDLE DEMO
Well, ok, here it goes.
In SQL Server you can use this...
SELECT word = d.value('.', 'nvarchar(max)')
FROM
(SELECT xmlWords = CAST(
'<a><i>' + replace([Message], ' ', '</i><i>') + '</i></a>' AS xml)
FROM MyMessageTbl) T(c)
CROSS APPLY c.nodes('/a/i') U(d)
And I hope that for MySQL you can use the same thing, using XML support - ExtractValue() etc.
EDIT: explanation
- replace([Message], ' ', '</i><i>') replaces e.g. 'my word' with 'my</i><i>word'
- then I add the beginning and the end of xml -> '<a><i>my</i><i>word</i></a>', so I have a valid xml... and cast it to xml type to be able to do something with it
- I select from that xml and shred xml nodes '/a/i' it to rows using CROSS APPLY c.nodes('/a/i');
alias rows using U(d), so one 'i' maps to column d (e.g. 'my')
- d.value('.', 'nvarchar(max)') extracts node content and casts it to character type