I'm working with a MySQL database that contains a substantial amount of data (about 10.000 records). The data in the database is logging of a machine maintenance, one of the fields contains a basic timeline (just steps that are timestamped) explaining all the work done. In this field I'm looking for certain strings that can indicate certain procedures (i.e. ABC123.ABC, abc111.abc, abc001.abc).
I'm looking for matches in this field with pattern matching like such
SELECT * FROM [tablename]
WHERE `work_performed` LIKE '% ______.___ %'
ORDER BY id DESC;`
The regex is very general but I can specify that further myself.
However, since the field which contains the string I'm looking for can be very large (up to 2364763 characters) i want to return the records matching the pattern specified but I also want to return a field that contains just the matched expression so I can confirm it is actually what I'm looking for and can use that string further.
I have found people with the same issue but I cannot reproduce their results.
Something like this might work?:
SELECT *, SUBSTRING(`work_performed`,
patindex('%[0-9][0-9][0-9]%', `work_performed`)-1, 5) as match
FROM [tablename]
WHERE `work_performed`LIKE '% ______.___ %'
I would like to get output that looks somewhat like this:
+----+-------------------------------------------+------------+
| id | work_performed | match |
+----+-------------------------------------------+------------+
| 1 | 2017-02-26|10:59| Arrival: admin1 | ABCD12.adb |
| | 2017-02-26|10:59| diagnosed error ab-0001 | |
| | 2017-02-26|11:02| ran ABCD12.adb | |
| | 2017-02-26|11:03| system back online | |
+----+-------------------------------------------+------------+
| 2 | 2017-02-26|10:59| Arrival: admin34 | abc123.ags |
| | 2017-02-26|10:59| diagnosed error WP1234 | |
| | 2017-02-26|11:02| ran abc123.ags | |
| | 2017-02-26|11:03| system back online | |
+----+-------------------------------------------+------------+
I apologise if I didn't give enough details but I'm an intern at a major company and we have very strict rules about confidentiality.
If there is a need for any additional information I will try to.
EDIT
I have been trying to search for the string I'm looking for with regexp, but I cant get it to work as I want to, here is what I tried:
SELECT * FROM tablename
WHERE `work_performed` regexp '% ([a-z]^3)([0-9]^3).([a-z]^3) %'
ORDER BY id DESC;
The solution using CONCAT, SUBSTR, SUBSTRING_INDEX and LOCATE functions:
SELECT
CONCAT(SUBSTRING_INDEX(SUBSTRING_INDEX(work_performed, '.', 1), ' ', - 1),
'.',
SUBSTR(SUBSTRING_INDEX(work_performed, '.', - 1), 1,
LOCATE(' ', SUBSTRING_INDEX(work_performed, '.', - 1))
)
) m
FROM
tablename
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html
DEMO link
Related
I have this type of string
'160f7a4a-766a-4c23-a155-8bd3f7389f77\', \'63233bfc-b663-4c73-890b-00a48d79c4dc'
In one column and I want like
'160f7a4a-766a-4c23-a155-8bd3f7389f77','63233bfc-b663-4c73-890b-00a48d79c4dc'
This type of result in MySQL
i have to perform query like
SELECT * FROM kapp_staging.kols where `kol_id` in (select REPLACE(json_id,'\'',"'") FROM kapp_staging.news_items
where `id` = '991'))
in where in clause i have subquery and in subquery
i geting
'160f7a4a-766a-4c23-a155-8bd3f7389f77\', \'63233bfc-b663-4c73-890b-00a48d79c4dc'
this type of value
so i need to remove \ from value so my where in query work fine.
i have data like:
Kols table
| id | kol_id | name | data |
|----|---------------------------------------- |---------| ------|
| 1 |160f7a4a-766a-4c23-a155-8bd3f7389f77 | balwant | data |
| 2 |63233bfc-b663-4c73-890b-00a48d79c4dc | vikram | data |
news items
| id | json_id | data |
|----|-----------------------------------------------------------------------------------------|---------|
| 991 | {'\160f7a4a-766a-4c23-a155-8bd3f7389f77\','\160f7a4a-766a-4c23-a155-8bd3f7389f77\'} | data |
I tried many ways but didn't get this response.
Thanks in Advance : )
The backslashes aren't in the data, they're just used to escape the quotes when inserting into the table. So you don't need to remove them.
However, you can't use IN to match values in a comma-delimited list, you need to use FIND_IN_SET(); see Search with comma-separated value mysql
You also need to remove the quotes and curly braces before you can use FIND_IN_SET().
SELECT DISTINCT k.*
FROM kols AS k
JOIN news_items AS n
ON FIND_IN_SET(k.kol_id,
REPLACE(REPLACE(REPLACE(json_id, '{', ''), '}', ''), "'", ''))
DEMO
Things would be much easier if you normalized your data and put the list of IDs into a separate table with one row per ID.
I'm trying to create a report in ReportBuilder (Digital Metaphors, not Microsoft) and I'm having trouble getting the SQL to do what I want.
I have one table with a field building:
| building |
+------------+
| WhiteHouse |
| TajMahal |
and another table with a field locations:
| id | locations |
+----+-----------------------------------------------------------------+
| 1 | WhiteHouse:RoseGarden,WhiteHouse:MapRoom,TajMahal:MainSanctuary |
| 2 | TajMahal:NorthGarden,WhiteHouse:GreenRoom |
I would like to create a table showing how many times each building is used in locations, like so:
| building | count |
+------------+-------+
| WhiteHouse | 3 |
| TajMahal | 2 |
The characters : and , are never used in building or room names. Even a quick-and-dirty solution that assumes that building names never appear in room names would be good enough for me.
Of course this would be easy to do in just about any sane programming language (total over something like /\bWhiteHouse:/); the trick will be getting RB to do it. Suggestions for workarounds are welcome.
it is possible to split locations string into pieces using the "," and ":" characters as seperators as follows in SQL Server with the help of a custom sql split function
select
p2.val,
count(p2.val)
from locations l
cross apply dbo.split(l.locations,',') p1
cross apply dbo.split(p1.val,':') p2
inner join building b
on b.building = p2.val
group by p2.val
I'm not sure there is a similar one in mysql, if so please check following solution as a template
You can try this, probably not the fastest, but certainly easier solution.
SELECT t1.building,
( SELECT SUM( ROUND( (LENGTH(t2.locations)
- LENGTH(REPLACE(t2.locations, concat(t1.building, ':'), ''))
) / (LENGTH(t1.building) + 1)
)
)
FROM table2 AS t2
) as count
FROM table1 as t1
SQL Fiddle Demo
I have my table like this:
|name |
-----------------
|Joseph Jackson |
|Aiden Chase |
|Luke Benjamin |
|Joseph |
|Joseph2 |
If I search for the word Joseph (SELECT * from myTable where name="Joseph" ) I woud get only the last result:
|name |
-----------------
|Joseph |
If I search for the word Jackson, I won't get any results.
That is what I DON'T want.
What I want is to get the records that exist in the exact word searched, for example:
if the word searched is Joseph, I woud get:
|name |
-----------------
|Joseph |
|Joseph Jackson |
*Notice that Joseph2 is not in the result set.
If the word searched is Jackson, I woud get:
|name |
-----------------
|Joseph Jackson |
*But I cannot use like '%Jose%' (the use of like) cuz I will get Joseph2 and I want the exact word(Jose).
*If the word searched is Jose for example I shouldn't get any result, cuz Jose is not in the data (also I shouldn't get records that contain the Joseph word).
The only way I've found is using regex for example:
SELECT * from myTable where REGEXP [[:<:]]Joseph[[:>:]]
|name |
-----------------
|Joseph |
|Joseph Jackson |
SELECT * from myTable where REGEXP [[:<:]]Jackson[[:>:]]
|name |
-----------------
|Joseph Jackson |
I want this results but without using regex and whithout rlike, is there any way? How? thanks.
This screams for FULLTEXT search
ALTER TABLE T ADD FULLTEXT INDEX (name);
SELECT * FROM T WHERE MATCH (name) AGAINST ('+Joseph' IN BOOLEAN MODE);
FIDDLE
Although full text as #Mihai suggests is definitely the way to go for production, if you want to do a one-off search without building extra indices you can just use LIKE by adding spaces around the names and search for the name including surrounding spaces;
SELECT * FROM myTable
WHERE CONCAT(' ', name, ' ') LIKE CONCAT('% ', 'joseph', ' %')
Note that this will definitely not use any indexes, so can be useful for admin purposes but not for a production application that cannot handle full table scans.
allow your stored procedure to accept a parameter for #name then you can use the WHERE clause
WHERE name = #name
I'm trying to merge rows in MySQL using the following code:
SELECT
type,
name,
GROUP_CONCAT(code SEPARATOR ',') AS code
FROM
`table1`
WHERE
name = '%name%' AND type = 'type'
GROUP BY
name
However no changes to DB entries occur which is the first problem.
The database looks like this:
type | name | code
-----|-------|-------
A | Milk2 | 143521
-----|-------|-------
A | Milk3 | 987564
-----|-------|-------
B | Oil | 656435
-----|-------|-------
Which I'm trying to make look like:
type | name | code
-----|-------|---------------
A | Milk | 143521, 987564
-----|-------|---------------
B | Oil | 656435
-----|-------|---------------
As you can see, names may be slightly different so this is another problem.
I am wondering whether there is any way to merge rows when, say the first four letters of the name match?
Thanks in advance.
MySQL has several string functions which might help. There's LEFT(name, 4) and you might also want to look at SOUNDEX(name), which implements the Soundex algorithm to hash words alike which sound alike. For example:
select soundex('smith'), soundex('smythe')
+ --------------------- + ---------------------- +
| soundex('smith') | soundex('smythe') |
+ --------------------- + ---------------------- +
| S530 | S530 |
+ --------------------- + ---------------------- +
1 rows
Or, using the example from your question:
select soundex('milk2'), soundex('milk3')
+ --------------------- + --------------------- +
| soundex('milk2') | soundex('milk3') |
+ --------------------- + --------------------- +
| M420 | M420 |
+ --------------------- + --------------------- +
1 rows
Your query would look something like this:
SELECT
type,
GROUP_CONCAT(DISTINCT(name) SEPARATOR ',') AS name, // note that since you've grouped on SOUNDEX(name) you can't just select name (MySQL may let you but will choose the first one
GROUP_CONCAT(code SEPARATOR ',') AS code
FROM
`table1`
WHERE
name LIKE '%name%' AND type = 'type'
GROUP BY
type, SOUNDEX(name)
I hope this is helpful!
You cannot use GROUP BY name here, as the name is always different, and you need to use LIKE instead of = when using wildcards.
The following should give you the result you're looking for
SELECT
type , name, GROUP_CONCAT( code SEPARATOR ',' ) AS all_codes
FROM `table1`
name LIKE '%name%' AND type = 'type'
I have a SQL table with the following values:
+---------+----------+
| post_id | path |
+---------+----------+
| 1 | 1/ |
| 2 | 1/2/ |
| 3 | 1/2/3/ |
| 4 | 1/2/3/4/ |
| 5 | 1/2/5/ |
+---------+----------+
How can I create a query that would get the path with the exact number of values separated by slashes?
For example, if I wanted all post_ids where the path is exactly 1/%/%/ (where each % represents a single number), meaning return anything of the form 1/2/3/, 1/2/5/, but not 1/2/3/4/.
Here's one option using regexp:
select *
from yourtable
where path regexp '1/[0-9]/[0-9]/$'
SQL Fiddle Demo
There are several ways to do that:
MySQL LIKE operator.
The LIKE operator provides two wildcard characters, the percentage % ( match any string of zero or more characters), and underscore _ ( match any single character ).
SELECT * FROM `table` WHERE `path` LIKE '1/_/_/'
SELECT * FROM `table` WHERE `path` LIKE '1/%/%/'
MySQL Regular Expressions.
SELECT * FROM `table` WHERE `path` regexp '^1/[0-9]/[0-9]/$'
Hierarchical Data in MySQL
Since this structure involves hierarchical data maybe you should consider to change the table structure to something that represents actual hierarchy. http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ has an excellent tutorial about the subject.