I have this query, works fine for view and csv export from phpmyadmin.
Is possible create a loop without repeat? thanks!
SELECT
id, date, name,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 1), '(', -1) AS op,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 4), '-', -3) AS dt,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, ')', 1), '-', -1) AS hour,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '(', 2), '-', -1) AS note
FROM center
WHERE center.date BETWEEN '2019-08-01 00:00:00' AND '2019-12-31 00:00:00'
and message!= ''
HAVING op = 'op1' OR op = 'op2'
UNION SELECT
id, date, name,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 6), '(', -1) AS op,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 9), '-', -3) AS dt,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, ')', 2), '-', -1) AS hour,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '(', 3), '-', -1) AS note
FROM center
WHERE center.date BETWEEN '2019-08-01 00:00:00' AND '2019-12-31 00:00:00'
and message!= ''
HAVING op = 'op1' OR op = 'op2'
UNION SELECT.... more
You can test this Query. It split a max. of 10 pieces from a row.
SELECT `id`,`date`,`name`,CONCAT('op',`op`) as op,`dt`,`hour`,`note`
,subid,cols -- only for test. you can remove this line
FROM (
SELECT c.id,c.date,c.name,
cnt.*,
-- count the pieces in one row
(LENGTH(message)-LENGTH(replace(message,'(op','')))/3 as cols,
-- Split String in piece and store in #content
#content := SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(' (op ',c.message,' (op'), ' (op', subid+3), ' (op', -1)
, SUBSTRING_INDEX(#content, ' - ',1) as op
, SUBSTRING_INDEX( SUBSTRING_INDEX(#content, ' - ',2), ' - ',-1) as dt
, TRIM( TRAILING ')' FROM SUBSTRING_INDEX( SUBSTRING_INDEX(#content, ' - ',3), ' - ',-1)) as hour
, SUBSTRING_INDEX( SUBSTRING_INDEX(#content, ' - ',4), ' - ',-1) as note
FROM center c
CROSS JOIN (
SELECT 0 as subid UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9
) as cnt
) as result
WHERE
subid < cols
AND `date` BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
AND op in (1,2)
ORDER BY id,subid,cols;
Here is a Sample : http://www.sqlfiddle.com/#!9/8bc3b4/60
Related
I enter in the database the value with this format 1 000.00.
I want to add two values of this format, for example 1 000.00 + 4 000.00 like this:
CAST(SUM(1 000.00 + 4 000.00) AS DECIMAL (15 , 2 )) AS Pago
the returned value is 5 and should be 5 000.00
Sum 2 values and finally add a space
-- MySQL
SELECT INSERT((SUM(CAST(REPLACE('1 000.00', ' ', '') AS decimal(15, 2)) + CAST(REPLACE('4 000.00', ' ', '') AS decimal(15, 2)))), 2, 0, ' ') sum_total
Please check url https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=b8ab1e7c4c1d2ab596fbc1fe58754cf8
Add these two values in a table
SELECT INSERT((SUM(CAST(REPLACE(apago, ' ', '') as decimal(15, 2)))), 2, 0, ' ') pago FROM test;
Please check this url https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=65fa6af1bedd4a1acce01dc0ea700dd6
I resolved it this way. First I removed the space in the string like this:
SELECT Id, Total, Metodo, REPLACE(Pago, ' ', '') AS Pago
FROM dados.Orcamento
Then I added the string:
SELECT B.Id, B.Total, B.Metodo, CAST(SUM(B.Pago) AS DECIMAL (15 , 2 )) AS Pago
FROM
(SELECT Id, Total, Metodo, REPLACE('Pago', ' ', '') AS Pago
FROM dados.Orcamento) AS B GROUP BY B.Id, B.Metodo, B.Total ORDER BY B.Id ASC LIMIT 1
So the 5000.00 returned
I am want to archive daily price statistics in MySQL 5.6 where I also use 25/50/75 percentiles. The formulas I found seem to work but are rounded to integers.
How can I get the 25/50/75 percentiles of price with 2 decimals precision?
INSERT INTO prices_daily
(DATE, ID, PRICE_MIN, PRICE_MAX, PRICE_AVG, `PRICE_25PZTL`, `PRICE 50PZTL`, `PRICE_75PZTL`, STRENGTH)
SELECT
DATE,
ID,
ROUND(MIN(price),2) AS PRICE_MIN,
ROUND(MAX(price),2) AS PRICE_MAX,
ROUND(AVG(price),2) AS PRICE_AVG,
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(price ORDER BY price SEPARATOR ','), ',', 25/100 * COUNT(*) + 1), ',', -1) AS DECIMAL) AS 'PRICE_25PZTL',
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(price ORDER BY price SEPARATOR ','), ',', 50/100 * COUNT(*) + 1), ',', -1) AS DECIMAL) AS 'PRICE_50PZTL',
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(price ORDER BY price SEPARATOR ','), ',', 75/100 * COUNT(*) + 1), ',', -1) AS DECIMAL) AS 'PRICE_75PZTL',
count(ID) AS STRENGTH
FROM
`articles`
WHERE
DATE = CURDATE()
GROUP BY
DATE,
ID
ORDER BY
STRENGTH DESC
I have a case where I will get input for products and their values separated with a delimited special character. Using this string I need to separate products and their values to MySQL Rows like below.
Input:
{"1301":29.00,"1302":25.01,"1306":50.09,"1678":100.00}
Output:
Product ID Value
1301 29.00
1302 25.01
1306 50.09
1678 100.00
Here the products Id counts are dynamic, we can get n count every time. Please help me getting the above output in MySQL.
MySQL only solution with JSON functions.
Query
SELECT
TRIM(REPLACE(
SUBSTRING_INDEX(
SUBSTRING_INDEX(json_parsed, ',', number_generator.number)
, ','
, -1
)
, '"'
, ''
)) AS 'Product ID'
, JSON_EXTRACT(json, CONCAT('$.', SUBSTRING_INDEX(
SUBSTRING_INDEX(json_parsed, ',', number_generator.number)
, ','
, -1
))) AS 'Value'
FROM (
SELECT
#row := #row + 1 AS number
FROM (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row1
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row2
CROSS JOIN (
SELECT #row := 0
) init_user_params
) AS number_generator
CROSS JOIN (
SELECT
SUBSTRING(json_keys, 2, json_keys_length - 2) AS json_parsed
, json_keys
, json
, JSON_LENGTH(json_keys) AS json_array_length
FROM (
SELECT
JSON_KEYS(record.json) AS json_keys
, json
, LENGTH(JSON_KEYS(record.json)) AS json_keys_length
FROM (
SELECT
'{"1301":29.00,"1302":25.01,"1306":50.09,"1678":100.00}' AS json
FROM
DUAL
) AS record
) AS json_information
) AS json_init
WHERE
number_generator.number BETWEEN 0 AND json_array_length
Result
| Product ID | Value |
| ---------- | ----- |
| 1301 | 29.0 |
| 1302 | 25.01 |
| 1306 | 50.09 |
| 1678 | 100.0 |
see demo
You really should be treating this like JSON, but you can use brute-force string methods. Here is one method:
select replace(substring_index(str, ':', 1), '"', '') as product_id, substring_index(str, ':', -1) as value
from (select replace(replace(substring_index(#x, ',', 1), '{', ''), '}', '') as str) x
union all
select replace(substring_index(str, ':', 1), '"', '') as product_id, substring_index(str, ':', -1) as value
from (select replace(replace(substring_index(substring_index(#x, ',', 2), ',', -1), '{', ''), '}', '') as str) x
union all
select replace(substring_index(str, ':', 1), '"', '') as product_id, substring_index(str, ':', -1) as value
from (select replace(replace(substring_index(substring_index(#x, ',', 3), ',', -1), '{', ''), '}', '') as str) x
union all
select replace(substring_index(str, ':', 1), '"', '') as product_id, substring_index(str, ':', -1) as value
from (select replace(replace(substring_index(substring_index(#x, ',', 4), ',', -1), '{', ''), '}', '') as str) x;
along with a db<>fiddle.
I wrote query like
SELECT
SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 1) AS level1,
IF(#num_lines > 1, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 2), ',', -1), '') AS level2,
IF(#num_lines > 2, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 3), ',', -1), '') AS level3,
IF(#num_lines > 3, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 4), ',', -1), '') AS level4,
IF(#num_lines > 4, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 5), ',', -1), '') AS level5
FROM hrm_t_interview inter,
(SELECT #num_lines := 1 + LENGTH(CHR_SKILLLEVELS) - LENGTH(REPLACE(CHR_SKILLLEVELS, ',', '')) FROM hrm_t_interview WHERE INT_APPLICANTID=15) temp
WHERE inter.INT_APPLICANTID=15
I displayed values like
level1 | level2 | level3
======================================
4 | 3 | 5
I want to display values like
column1 | column2
========================
level1 | 4
level2 | 3
level3 | 5
Please help me using mysql.
Crude way would be to use multiple unioned queries, something like this:-
SELECT 'level1' AS column1, SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 1) AS column2
FROM hrm_t_interview inter
INNER JOIN
(
SELECT INT_APPLICANTID, 1 + LENGTH(CHR_SKILLLEVELS) - LENGTH(REPLACE(CHR_SKILLLEVELS, ',', '')) AS num_lines
FROM hrm_t_interview
GROUP BY INT_APPLICANTID
HAVING num_lines > 0
) temp
ON inter.INT_APPLICANTID = temp.INT_APPLICANTID
WHERE inter.INT_APPLICANTID=15
UNION
SELECT 'level2' AS column1, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 2), ',', -1) AS column2
FROM hrm_t_interview inter
INNER JOIN
(
SELECT INT_APPLICANTID, 1 + LENGTH(CHR_SKILLLEVELS) - LENGTH(REPLACE(CHR_SKILLLEVELS, ',', '')) AS num_lines
FROM hrm_t_interview
GROUP BY INT_APPLICANTID
HAVING num_lines > 1
) temp
ON inter.INT_APPLICANTID = temp.INT_APPLICANTID
WHERE inter.INT_APPLICANTID=15
UNION
SELECT 'level3' AS column1, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 3), ',', -1) AS column2
FROM hrm_t_interview inter
INNER JOIN
(
SELECT INT_APPLICANTID, 1 + LENGTH(CHR_SKILLLEVELS) - LENGTH(REPLACE(CHR_SKILLLEVELS, ',', '')) AS num_lines
FROM hrm_t_interview
GROUP BY INT_APPLICANTID
HAVING num_lines > 2
) temp
ON inter.INT_APPLICANTID = temp.INT_APPLICANTID
WHERE inter.INT_APPLICANTID=15
UNION
SELECT 'level4' AS column1, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 4), ',', -1) AS column2
FROM hrm_t_interview inter
INNER JOIN
(
SELECT INT_APPLICANTID, 1 + LENGTH(CHR_SKILLLEVELS) - LENGTH(REPLACE(CHR_SKILLLEVELS, ',', '')) AS num_lines
FROM hrm_t_interview
GROUP BY INT_APPLICANTID
HAVING num_lines > 3
) temp
ON inter.INT_APPLICANTID = temp.INT_APPLICANTID
WHERE inter.INT_APPLICANTID=15
UNION
SELECT 'level5' AS column1, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', 5), ',', -1) AS column2
FROM hrm_t_interview inter
INNER JOIN
(
SELECT INT_APPLICANTID, 1 + LENGTH(CHR_SKILLLEVELS) - LENGTH(REPLACE(CHR_SKILLLEVELS, ',', '')) AS num_lines
FROM hrm_t_interview
GROUP BY INT_APPLICANTID
HAVING num_lines > 4
) temp
ON inter.INT_APPLICANTID = temp.INT_APPLICANTID
WHERE inter.INT_APPLICANTID=15
A bit more elegant might be to generate a range of rows, one for each possible delimited value.
Not tested but something like this:-
SELECT CONCAT('level', temp2.iCnt) AS column1, SUBSTRING_INDEX(SUBSTRING_INDEX(inter.CHR_SKILLLEVELS, ',', temp2.iCnt), ',', -1) AS column2
FROM hrm_t_interview inter
INNER JOIN
(
SELECT 1 + LENGTH(CHR_SKILLLEVELS) - LENGTH(REPLACE(CHR_SKILLLEVELS, ',', '')) AS num_lines
FROM hrm_t_interview
GROUP BY INT_APPLICANTID
) temp
ON inter.INT_APPLICANTID = temp.INT_APPLICANTID
INNER JOIN
(
SELECT 0 AS iCnt UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
) temp2
ON temp.num_lines >= temp2.iCnt
WHERE inter.INT_APPLICANTID=15
If you can paste up some test data I will check the sql.
I am trying to divide data in one onf the tables on my MySQL database.
Column contains data like this:
de:"Sweatjacke*";en:"jacket*";pl:"bluza*";
de:"*";en:"*";pl:"bluza*";
fr:"*";de:"*";en:"*";pl:"dres junior*";cz:"*";
pl:"bluza";
And I am trying to divide all of the translations into separate columns. Already came with solution to do this by using:
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 1), ';', -1) as tr1,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 2), ';', -1) as tr2,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 3), ';', -1) as tr3,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 4), ';', -1) as tr4,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 5), ';', -1) as tr5
FROM product;
statement, but that results in:
tr1 tr2 tr3 tr4 tr5
fr:"*" de:"*" en:"*" pl:"bluza*" cz:"*"
fr:"*" de:"Sweatjacke*" en:"jacket*" pl:"bluza*" cz:"*"
de:"Sweatjacke*" en:"jacket*" pl:"bluza*"
And I want to have the results gruped by translation type (pl/de/en) so in each collumn one type of translatoin is present. For example in column1 = pl:, column2 = en: etc.
Any one came across similar problem and knows a way to solve it?
You need to unpivot the data, then select the first and second part of each value and then re-aggregate it.
However, a better form for the data is really to have language/translation. The following produces this:
select substring_index(tr, ':', 1) as l, substring_index(tr, ':', 2) as t, name
from (select SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', n.n), ';', -1) as tr, n, name
from product p cross join
(select 1 as n union all select 2 union all select 3 union all select 4 union all
select 5
) n
) n
You would probably want an "id" column or "word" column to identify each row, rather than the name column.
You can now pivot this result to get what you want:
select max(case when l = 'en' then name end) as en,
max(case when l = 'fr' then name end) as fr,
max(case when l = 'de' then name end) as de,
max(case when l = 'pl' then name end) as pl,
max(case when l = 'cz' then name end) as cz
from (select substring_index(tr, ':', 1) as l, substring_index(tr, ':', 2) as t, name
from (select SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', n.n), ';', -1) as tr, n, name
from product p cross join
(select 1 as n union all select 2 union all select 3 union all select 4 union all
select 5
) n
) n
) lt
group by name;
Managed to solve it by using some of the string related functions funcitons:
SELECT
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "pl:", name ) , 150 ) , ';', 1 ) AS pl,
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "en:", name ) , 150 ) , ';', 1 ) AS en,
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "de:", name ) , 150 ) , ';', 1 ) AS de,
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "fr:", name ) , 150 ) , ';', 1 ) AS fr
FROM product
Thanks to everyone for help.
As far as I understand you want to UNPIVOT your data. There is no such function in MySQL, so you might want to export your data into MSSQL (you can use free MSSQL Express) and use UNPIVOT function: http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx