How to select row which a certain text format? - mysql

Sorry for an unclear question coz I don't know how to ask correctly. Let me explain this. I'd like to search for some rows in mySQL. Which is only in this format - "product1" (text and number). While in my table. There're some other rows begins with "product" as well. But they're not followed by number.
Here's my table.
**product_db**
+----------+-------+
| key | value |
+----------+-------+
| product1 | 100 |
+----------+-------+
| product2 | 184 |
+----------+-------+
| product3 | 170 |
+----------+-------+
| productA | 210 |
+----------+-------+
| productB | 100 |
+----------+-------+
This is mySQL:
select * from product_db where key like 'product%'
After run the code. Every row shows up. Because they're all begins with "product". I expect only the first 3 rows that followed by number to be displayed. How can I write a command in mySQL.

you should use regex:
select * from product_db where key REGEXP '^product[0-9]+$';

SELECT 'product1' REGEXP '[product][0-9]';
+------------------------------------+
| 'product1' REGEXP '[product][0-9]' |
+------------------------------------+
| 1 |
+------------------------------------+
1 row in set (0.01 sec)
SELECT 'productA' REGEXP '[product][0-9]';
+------------------------------------+
| 'productA' REGEXP '[product][0-9]' |
+------------------------------------+
| 0 |
+------------------------------------+
1 row in set (0.00 sec)

Related

mysql query, different performance between = and IN

why there is this difference of time execution between these two queries even if they retrieve the same amount of rows from the same table?
select cognome, nome, lingua, count(*)
from archivio.utente
where cognome in ('rossi','pecchia','pirono')
group by cognome, nome, lingua;
…
…
…
| Rossi | Mario | it | 1 |
| Pironi | Luigi | it | 1 |
| Pecchia | Fabio | it | 1 |
+----------------------+---------+--------+----------+
779 rows in set (0.03 sec)
select cognome, nome, lingua, count(*)
from archivio.utente
where nome='corrado'
group by cognome, nome, lingua;
…
…
…
| Rossi | Mario | it | 1 |
| Pironi | Luigi | it | 1 |
| Pecchia | Fabio | it | 1 |
+----------------------+---------+--------+----------+
737 rows in set (0.47 sec)
from mysql documentation :
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain-join-types
when we use in
Only rows that are in a given range are retrieved, using an index to select the rows.
The key column in the output row indicates which index is used.
when we use =
A full table scan is done for each combination of rows
So in one case all lines are retrieved and compared, in another case just a range.

Changing the fractions in sql

I have fractions as string in my database and it is currently like this:
3/8
I want to change to this:
<sup>3</sup>⁄<sub>8</sub>
I have many fractions like this. How do I change them at one shot in SQL? I know I need to use Regular Expressions but not sure how to use it.
What I have tried so far:
UPDATE question_table
SET `option` = Replace(`option`, ?? ,??)
WHERE `option` LIKE '%/%'
Not sure what to fill up in ??.
SELECT * FROM strings;
+--------+
| string |
+--------+
| 19/32 |
| 3/8 |
| 5/16 |
+--------+
SELECT *
, CONCAT('<sup>'
, SUBSTRING_INDEX(string,'/',1)
, '</sup>⁄<sub>'
, SUBSTRING_INDEX(string,'/',-1)
,'</sub>'
) x
FROM strings;
+--------+-----------------------------------+
| string | x |
+--------+-----------------------------------+
| 19/32 | <sup>19</sup>⁄<sub>32</sub> |
| 3/8 | <sup>3</sup>⁄<sub>8</sub> |
| 5/16 | <sup>5</sup>⁄<sub>16</sub> |
+--------+-----------------------------------+
UPDATE strings
SET string = CONCAT('<sup>'
, SUBSTRING_INDEX(string,'/',1)
, '</sup>⁄<sub>'
, SUBSTRING_INDEX(string,'/',-1)
, '</sub>'
);
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0
SELECT * FROM strings;
+-----------------------------------+
| string |
+-----------------------------------+
| <sup>19</sup>⁄<sub>32</sub> |
| <sup>3</sup>⁄<sub>8</sub> |
| <sup>5</sup>⁄<sub>16</sub> |
+-----------------------------------+

mySql Max function ot returning exact result

I don't know why i am not getting the exact result
SELECT MAX(MID(order_id,3,20)) As Id FROM `tbl_orders` WHERE `domain_id`=2
+------------+
| id |
+------------+
| 10121452 |
+------------+
Even i tried the same function without MID function
SELECT MAX(order_id) As Id FROM `tbl_orders` WHERE `domain_id`=2
+------------+
| id |
+------------+
| Hy10121452 |
+------------+
any my database have highest order
+--------+------------+
| id | order_id |
+--------+------------+
| 1 | Hy10121452 |
| 2 | Hy10121453 |
| 3 | Hy10121454 |
| 4 | Hy10121455 |
| 5 | Hy10121456 |
| 6 | Hy10121457 |
| 7 | Hy10121458 |
| 8 | Hy10121459 |
| 9 | Hy10121460 |
+--------+------------+
i have to increment in the highest number to generate new order No.
Is i am doing something wrong?
check your database -> table-> column the data does not contain the same values like this abc1 abc2 abc3 xxx1 if you differnt series then the result always wrong
Change MAX(MID(order_id,3,20)) to MAX(MID(order_id,3,))
Syntax:from W3School
SELECT MID(column_name,start[,length]) AS some_name FROM table_name;
where
column_name Required. The field to extract characters from
start Required. Specifies the starting position (starts at 1)
length Optional. The number of characters to return. If omitted, the MID() function returns the rest of the text
Since you want the highest id then you can use order by DESC and limit
SELECT order_id As Id FROM `tbl_orders` WHERE `domain_id`=2 ORDER BY order_id DESC LIMIT 1
Problem Solved i just have to rectify Order_id column it contains the duplicate entries. duplicate entries removed and problem solved like a charm.

MySQL HAVING Clause return empty set?

I am having a table below, and I need to write code that extract the rows with budget greater than the average budget.
+------+-----------------+--------+
| Code | Name | Budget |
+------+-----------------+--------+
| 14 | IT | 65000 |
| 37 | Accounting | 15000 |
| 59 | Human Resources | 240000 |
| 77 | Research | 55000 |
+------+-----------------+--------+
I know this works:
SELECT * FROM Departments WHERE Budget > (SELECT AVG(Budget) FROM Departments);
but this looks ugly. This post seems to suggest having clause can simplify the query into:
SELECT * FROM Departments HAVING Budget > AVG(Budget);
but it returns empty set. Any ideas?
Thanks
This is because AVG() is aggregation function which should be used GROUP BY or with other Aggregation functions.
If not, SELECT would returns single row. for example:
mysql> SELECT * FROM test;
+------+--------+
| code | budget |
+------+--------+
| 14 | 65000 |
| 37 | 15000 |
| 59 | 240000 |
| 77 | 55000 |
+------+--------+
4 rows in set (0.00 sec)
mysql> SELECT code, budget, AVG(budget) FROM test;
+------+--------+-------------+
| code | budget | AVG(budget) |
+------+--------+-------------+
| 14 | 65000 | 93750.0000 | we got one row.
+------+--------+-------------+
1 row in set (0.00 sec)
In this case, HAVING budget > AVG(budget) means 65000 > 93750 which is false, so that returns empty list.
Your first attampt does not look like 'ugly' ;)
In mySQL, having an aggregation column with SELECT * will return the first row only.
This SQL Fiddle shows that:
SELECT *, AVG(BUDGET) FROM Departments;
will return only the first row and the average of budget of all rows.
Then, as in your first row, the budget is smaller than the average of budgets, it will return no rows.
I believe your UGLY (I don't think it is ugly) query is a good solution for this.

Best way to find a line in MySQL by piece of value

Database:
+----+------------+
| id | somevalue |
+----+------------+
| 1 | 1000 |
+----+------------+
| 2 | 1001 |
+----+------------+
| 3 | 1002 |
+----+------------+
| 4 | 10021 |
+----+------------+
Question:
What is the best way to find a row by a string which contains piece of "somevalue"?
1. Let's say string is 1002123456. So in this case I must find row with ID 4.
2. Let's say string is 1002345678. So in this case I must find row with ID 3.
Would "MySQL LIKE" work in this scenario?
UPDATE:
Database has 60k rows and "somevalue" should be matched from the front. Because piece of "somevalue" might contain different rows, for example:
+----+------------+
| id | somevalue |
+----+------------+
| 1 | 1000 |
+----+------------+
| 27 | 371000 |
+----+------------+
I am looking for a way to make the process as fast as possible.
SELECT * FROM `db`.`table` WHERE 'someval' LIKE CONCAT('%',`field` , '%') ;
The RLIKE allowes you to match regular expressions in the fields
SELECT * FROM 'table' WHERE 'searchNumber' LIKE CONCAT('%', somevalue, '%')