MySQL prefix SET field values with custom string - mysql

I have a MySQL 5 database table field media like set('audio','video','photo')
What i need to do, is in single SELECT statement prefix it's values with some custom string and space after it, if any of the values are present. For example:
audio,video becomes mediaaudio mediavideo
photo becomes mediaphoto
The specifics of the data does not require an external relationship table to be made for corresponding values, so set is sufficient for the current task. I need to prefix them to uniquely identify them later in search results.
Real example:
id media
1 audio,video
2 audio
3 video
4 photo,video
5
Expected result:
id media
1 mediaaudio mediavideo
2 mediaaudio
3 mediavideo
4 mediaphoto mediavideo
5

Here's one way to do it with INSTR, CONCAT, REPLACE and LENGTH:
SELECT ID,
CASE WHEN INSTR(YourField, ',') > 0
THEN CONCAT('media', REPLACE(YourField, ',', ' media'))
WHEN LENGTH(YourField) > 0
THEN CONCAT('media', YourField)
ELSE ''
END media
FROM YourTable
And the Fiddle.
Good luck.

Related

How to get the first record of each type in sequence?

Table Data:
ID
Type
1
A
2
A
3
B
4
A
5
A
6
B
7
B
8
A
9
A
10
A
How to get only rows with IDs 1,3,4,6,8, or the first records on type-change by single query?
We were doing this in code using multiple queries and extensive processing especially for large data, is there a way to do this in a single query?
Use LAG() window function to get for every row the previous row's type and compare it to the current type.
Create a flag column that is true if the 2 types are different and use it to filter the table:
WITH cte AS (
SELECT *, type <> LAG(type, 1, '') OVER (ORDER BY id) flag
FROM tablename
)
SELECT * FROM cte WHERE flag;
I assume that the column type does not contain empty values (nulls or
empty strings).
See the demo.

Recursively running a MySQL function

I have a function in MySQL that needs to be run about 50 times (not a set value) in a query. the inputs are currently stored in an array such as
[1,2,3,4,5,6,7,8,9,10]
when executing the MySQL query individually it's working fine, please see below
column_name denotes the column it's getting the data for, in this case, it's a DOUBLE in the database
The second value in the MOD() function is the input I'm supplying MySQL from the aforementioned array
SELECT id, MOD(column_name, 4) AS mod_output
FROM table
HAVING mod_output > 10
To achieve the output I require* the following code works
SELECT id, MOD(column_name, 4) AS mod_output1, MOD(column_name, 5) AS mod_output2, MOD(column_name, 6) AS mod_output3
FROM table
HAVING mod_output1 > 10 AND mod_output2 > 10 AND mod_output3 > 10
However this obviously is extremely dirty, and when having not 3 inputs, but over 50, this will become highly inefficient.
Appart from calling over 50 individual querys, is there a better way to acchieve the same sort (see below) of output?
In escennce i need to supply MySQL with a list of values and have it run MOD() over all of them on a specified column.
The only data I need returned is the id's of the rows that match the MOD() functions output with the specified input (see value 2 of the MOD() function) where the output is less than 10
Please note, MOD() has been used as an example function, however, the final function required *should* be a drop in replacement
example table layout
id | column_name
1 | 0.234977
2 | 0.957739
3 | 2.499387
4 | 48.395777
5 | 9.943782
6 | -39.234894
7 | 23.49859
.....
(The title may be worded wrong, I'm not quite sure how else you'd explain what I'm trying to do here)
Use a join and derived table or temporary table:
SELECT n.n, t.id, MOD(t.column_name, n.n) AS mod_output
FROM table t CROSS JOIN
(SELECT 4 as n UNION ALL SELECT 5 UNION ALL SELECT 6 . . .
) n
WHERE MOD(t.column_name, n.n) > 10;
If you want the results as columns, you can use conditional aggregation afterwards.

MYSQL - Find rows, where part of search string matches part of value in column

I wasn't able to find this anywhere, here's my problem:
I have a string like '1 2 3 4 5' and then I have a mysql table that has a column, let's call it numbers, that look like this:
numbers
1 2 6 8 9 14
3
1 5 3 6 9
7 8 9 23 44
10
I am trying to find the easiest way (hopefully in a single query) to find the rows, where any of the numbers in my search string (1 or 2 or 3 or 4 or 5) is contained in the numbers column. In the give example I am looking for rows with 1,2 and 3 (since they share numbers with my search string).
I am trying to do this with a single query and no loops.
Thanks!
The best solution would be to get rid of the column containing a list of values, and use a schema where each value is in its own row. Then you can use WHERE number IN (1, 2, 3, 4, 5) and join this with the table containing the rest of the data.
But if you can't change the schema, you can use a regular expression.
SELECT *
FROM yourTable
WHERE numbers REGEXP '[[:<:]](1|2|3|4|5)[[:<:]]'
[[:<:]] and [[:<:]] match the beginning and end of words.
Note that this type of search will be very slow if the table is large, because it's not feasible to index it.
Here is a start point (split string function) : http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/ := SplitString(string,delimiter,position)
Create a function so it converts a string to an array := stringSplitted(string,delimiter)
Create a function so it compares two arrays :=arrayIntersect(array1, array2)
SELECT numbers
FROM table
WHERE arrayIntersect(#argument, numbers)
Two function definitions with loops and one single query without any loop
SELECT * FROM MyTable WHERE (numbers LIKE '%1%' OR numbers LIKE '%2%')
or you can also use REGEX something like this
SELECT * FROM events WHERE id REGEXP '5587$'

MySQL match area code only when given the full number

I have a database that lists a few area codes, area code + office codes and some whole numbers and a action. I want it to return a result by the digits given but I am not sure how to accomplish it. I have some MySQL knowledge but its not very deep.
Here is a example:
match | action
_____________________
234 | goto 1
333743 | goto 2
8005551212| goto 3
234843 | goto 4
I need to query the database with a full 10 digit number -
query 8005551212 gives "goto 3"
query 2345551212 gives "goto 1"
query 3337431212 gives "goto 2"
query 2348431212 gives "goto 4"
This would be similar to the LIKE selection, but I need to match against the database value instead of the query value. Matching the full number is easy,
SELECT * FROM database WHERE `match` = 8005551212;
First the number to query will always be 10 digits, so I am not sure how to format the SELECT statement to differentiate the match of 234XXXXXXX and 234843XXXX, as I can only have one match return. Basically if it does not match the 10 digits, then it checks 6 digits, then it will check the 3 digits.
I hope this makes sense, I do not have any other way to format the number and it has to be accomplished with just a single SQL query and return over a ODCB connection in Asterisk.
Try this
SELECT match, action FROM mytable WHERE '8005551212' like concat(match,'%')
The issue is that you will get two rows in one case .. given your data..
SELECT action
FROM mytable
WHERE '8005551212' like concat(match,'%')
order by length(match) desc limit 1
That should get the row that had the most digits matched..
try this:
SELECT * FROM (
SELECT 3 AS score,r.* FROM mytable r WHERE match LIKE CONCAT(SUBSTRING('1234567890',1,3),'%')
UNION ALL
SELECT 6 AS score,r.* FROM mytable r WHERE match LIKE CONCAT(SUBSTRING('1234567890',1,6),'%')
UNION ALL
SELECT 10 AS score,r.* FROM mytable r WHERE match LIKE CONCAT(SUBSTRING('1234567890',1,10),'%')
) AS tmp
ORDER BY score DESC
LIMIT 1;
What ended up working -
SELECT `function`,`destination`
FROM reroute
WHERE `group` = '${ARG2}'
AND `name` = 0
AND '${ARG1}' LIKE concat(`match`,'%')
ORDER BY length(`match`) DESC LIMIT 1

Comparing number in formatted string in MySQL?

I have a PolicyNo column in my table in MySQL with a format like this:
XXXX-000000
A four capital-case characters followed by a dash and a six digit number.
The six digit number is incremental, adding 1 for the next row, and the the four characters is always the same for all rows. The PolicyNo column is unique with a type of varchar(11).
If ordered, it will look like this:
XXXX-000001
XXXX-000002
XXXX-000003
...
Now I want to get all PolicyNo whose number is greater than a specified number.
For example: Retrieve all PolicyNo greater than 'XXXX-000100':
XXXX-000101
XXXX-000102
XXXX-000103
...
I test this query and it works fine, but I just didn't know if it is really safe to do such:
SELECT 'XXXX-000099' > 'XXXX-000098'
, 'XXXX-000099' > 'XXXX-000100'
, 'XXXX-000099' > 'XXXX-000101'
Result:
+-------------------------------+-------------------------------+-------------------------------+
| 'XXXX-000099' > 'XXXX-000098' | 'XXXX-000099' > 'XXXX-000100' | 'XXXX-000099' > 'XXXX-000101' |
+-------------------------------+-------------------------------+-------------------------------+
| 1 | 0 | 0 |
+-------------------------------+-------------------------------+-------------------------------+
Is there any other way to do this or is it already OK to use this?
Because your numbers are zero padded, as long as the four letter prefix is the same and always the same length, then this should work as MySQL will do a lexicographical comparison.
Note that one less 0 in the padding will cause this to fail:
SET #policy1 = 'XXXX-00099';
SET #policy2 = 'XXXX-000598';
SELECT #policy1, #policy2, #policy1 > #policy2 AS comparison;
=========================================
> 'XXXX-00099', 'XXXX-000598', 1
If you need to truly compare the numbers at the end, you will need to parse them out and cast them:
SET #policy1 = 'XXXX-00099';
SET #policy2 = 'XXXX-000598';
SELECT #policy1, #policy2,
CONVERT(SUBSTRING(#policy2, INSTR(#policy2, '-')+1), UNSIGNED) >
CONVERT(SUBSTRING(#policy2, INSTR(#policy2, '-')+1), UNSIGNED) AS comparison;
=========================================
> 'XXXX-00099', 'XXXX-000598', 0
You can also use SUBSTRING function provided by MySQL, like the following query.
SELECT count(*) FROM Table1 where substring(policyNo,6)>YOUR_RANGE;
here 6 is passed as the 6 digit number start from 6th position And if you do want to pass initial 4 charecter as well then you can use following query. Here second where clause will take intial 4 letters from the policyNo.
SELECT count(*) FROM Table1 where substring(policyNo,6)>YOUR_RANGE AND substring(policyNo,1,4) = 'ABCD'