Split mySQL column into many - mysql

Ive got a MySQL column that has a set of number that are separated by spaces. There is about 330 spaces..... and they are not all in the same place ( for each set)
Is there a way I can do this automatically, like via a query?
Or is this possible in Microsoft SQL?
Edit 1: I'm afraid I haven't really tried anything, - not to sure what to do.
Here is an example of one of the sets of numbers
3 10 13 18 0 0 175 215 177 173 213 203 592 272 0 175 215 177 173 215 177 172 208 203 592
It's very repetitive.

You can generate a list of numbers, then use those numbers cross joined against your data with SUBSTRING_INDEX to get the individual fields.
Something like this:-
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SomeField, ' ', aNum + 1), ' ', -1)
FROM SomeTable
CROSS JOIN
(
SELECT Units.aCnt + Tens.aCnt * 10 + Hundreds.aCnt * 100 AS aNum
FROM
(SELECT 0 AS aCnt 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) Units,
(SELECT 0 AS aCnt 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) Tens,
(SELECT 0 AS aCnt 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) Hundreds
) Sub1
WHERE LENGTH(SomeField) - LENGTH(REPLACE(SomeField, ' ', '')) >= aNum
SQL fiddle here:-
http://www.sqlfiddle.com/#!2/7c43a/4
Then find the person who designed the database table and explain to them about database design / normalisation / indexes.
EDIT - A way that can (just about) do this select, coping with the number of cols. It should return NULL for any col that doesn't exist for that row. Probably best used in a MySQL stored proc. It calculates the max number of cols and then generates some dynamic SQL to get those cols.
SET #sql = NULL;
SET SESSION group_concat_max_len = 1000000;
SELECT GROUP_CONCAT(aField ORDER BY aNum)
INTO #sql
FROM
(
SELECT (Units.aCnt + Tens.aCnt * 10 + Hundreds.aCnt * 100) AS aNum, CONCAT("IF(LENGTH(SomeField) - LENGTH(REPLACE(SomeField, ' ', '')) >= ", (Units.aCnt + Tens.aCnt * 10 + Hundreds.aCnt * 100), ", SUBSTRING_INDEX(SUBSTRING_INDEX(SomeField, ' ', ", (Units.aCnt + Tens.aCnt * 10 + Hundreds.aCnt * 100 + 1),"), ' ', -1), NULL) AS col",(Units.aCnt + Tens.aCnt * 10 + Hundreds.aCnt * 100)) AS aField
FROM (SELECT MAX(LENGTH(SomeField) - LENGTH(REPLACE(SomeField, ' ', ''))) AS MaxDelim FROM SomeTable) Sub1,
(SELECT 0 AS aCnt 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) Units,
(SELECT 0 AS aCnt 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) Tens,
(SELECT 0 AS aCnt 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) Hundreds
WHERE Units.aCnt + Tens.aCnt * 10 + Hundreds.aCnt * 100 <= Sub1.MaxDelim
) Sub2;
SET #sql = CONCAT('SELECT ', #sql,
' FROM SomeTable
');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SQL fiddle for this:-
http://www.sqlfiddle.com/#!2/a28ab2/2

Related

Fetching Only Unique Results From Sql Database

Database Table
ID Post Tags
1 Range rover range-rover,cars
2 Lamborghini lamborghini,cars
3 Kawasaki kawasaki,bikes
4 Yamaha R1 yamaha,r1,bikes
I Want to Remove Duplicate Values from Result sql
What i Get When i fetch tags (tags are in ,) from Database
SELECT Tags from posts;
Resut:
range-rover,cars lamborghini,cars kawasaki,bikes yamaha,r1,bikes
What I Need is not to show same result again.
range-rover,cars lamborghini kawasaki,bikes yamaha,r1
You can split your text using tally table and SUBSTRING_INDEX:
SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(t.tags, ',', n.n), ',', -1) AS val
FROM posts t
CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N 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) a
,(SELECT 0 AS N 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) b
) n
WHERE n.n <= 1 + (LENGTH(t.tags) - LENGTH(REPLACE(t.tags, ',', '')))
SqlFiddleDemo
If you need one row add GROUP_CONCAT:
SELECT GROUP_CONCAT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(t.tags, ',', n.n), ',', -1)) AS val
...
SqlFiddleDemo2

How to select only particular word start with # from sentence mysql query

let's explain briefly
this is very new topic, I want to fetch only particular word start with # from sentence for example
i have sentence like
Hi Majjx Uxud Xhhxhd Hx Dhx #hdhd Jdhhdhshhfd Hxhhd #bhd Hxhd Hxhhd Dhhdh www.myinnos.in Hdhd Xfhhxhd Xhhdh Xhx 9560233669 ndhdh Hxhhdh Dhh
from above sentence I have to fetch #hdhd
got a solution for my question, now I want to count and show the repeated words as count
select val from(
select (substring_index(substring_index(a, ' ', n.n), ' ', -1)) val
from (select id, message as a from filmbooknewsfeed) t
cross join(
select a.n + b.n * 10 + 1 n
from
(select 0 as n 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
) a,
(select 0 as n 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
) b
order by n
) n
where n.n <= 1 + (length(t.a) - length(replace(t.a, ' ', '')))
order by val asc
)x where val like '#%'
As I said, you need to convert the sentence into rows. Just in case, if in sentence you have more than 1 words start with #.
select val from(
select (substring_index(substring_index(a, ' ', n.n), ' ', -1)) val
from (
select 'Hi Majjx Uxud Xhhxhd Hx Dhx #hdhd Jdhhdhshhfd Hxhhd #bhd Hxhd Hxhhd Dhhdh www.myinnos.in Hdhd Xfhhxhd Xhhdh Xhx 9560233669 ndhdh Hxhhdh Dhh' as a
) t
cross join(
select a.n + b.n * 10 + 1 n
from
(select 0 as n 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
) a,
(select 0 as n 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
) b
order by n
) n
where n.n <= 1 + (length(t.a) - length(replace(t.a, ' ', '')))
order by val asc
)x where val like '#%'
Will give you #hdhd. even if you has more than 1 # in the sentence. This would give you correct result.
edit
If you want to group by result and sort by most occurence words like twitter tranding topic, modify your query like this (as query on the question)
select val,count(val) as cnt from(
select (substring_index(substring_index(a, ' ', n.n), ' ', -1)) val
from (select id, message as a from filmbooknewsfeed) t
cross join(
select a.n + b.n * 10 + 1 n
from
(select 0 as n 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
) a,
(select 0 as n 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
) b
order by n
) n
where n.n <= 1 + (length(t.a) - length(replace(t.a, ' ', '')))
order by val asc
)x where val like '#%'
group by val
order by cnt desc
You can do this using substring_index():
select substring_index(substring_index(substring_index(sentence, '#', 2), '#', -1), ' ', 1)

SQL row column sum with spaces between numbers

mysql table:
table_results:
id results
1 1 0 1 2 4 5
2 5 4 2 6
3 7 2 8 2 4
I'm creating a Yii gridview I need to
SELECT SUM(results) AS results2 FROM table_results WHERE id = 1:
for example I have to sum first row: 1+0+1+2+4+5 and make as results2 which = 15.
How to do that just in sql?
There is no need for dynamic SQL. You can use:
SqlFiddleDemo
SELECT sub.id, SUM(sub.val) AS `sum`
FROM
(
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(t.results, ' ', n.n), ' ', -1) AS val
FROM table_results t
CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N 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) a
,(SELECT 0 AS N 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) b
) n
WHERE n.n <= 1 + (LENGTH(t.results) - LENGTH(REPLACE(t.results, ' ', '')))
) sub
-- WHERE sub.id = 1
GROUP BY sub.id
One way to do this is using dynamic SQL. So, entirely within MySQL:
declare #sql varchar(2000);
select #sql = concat('select ', replace(results, ' ', '+'))
from table_results tr
where id = 1;
prepare s from #sql;
execute s;
deallocate prepare s;
As a note: Just because I answered the question does not mean that I condone the data structure.

Find elements in a set that are not in another set using native MySQL functions

I have two variables having comma separated IDs.
SET #Set1 = '1,2,3,4';
SET #Set2 = '3,2,5,6';
I want to get all elements in Set1 that are not in Set2 using just MySQL functions. In the above case,
the answer is: '1,4'.
Please note that I want to use only native MySQL functions.
the easiest way would be to normalize your set you want to find the results in and then use FIND_IN_SET() on the second set like so
SET #Set1 = '1,2,3,4';
SET #Set2 = '3,2,5,6';
SELECT col
FROM
( SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(#Set1, ',', n.digit+1), ',', -1) col
FROM (SELECT #set1) temp
JOIN(SELECT 0 digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) n
ON LENGTH(REPLACE(#Set1, ',' , '')) <= LENGTH(#Set1)-n.digit
ORDER BY n.digit
) t
WHERE NOT FIND_IN_SET(col, #set2);
if you want to capture as many comma separated digits as you can then just do this
SELECT col
FROM
( SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(#Set1, ',', n.digit+1), ',', -1) col
FROM (SELECT #set1) temp
JOIN
( SELECT
SEQ.SeqValue as digit
FROM
( SELECT (HUNDREDS.SeqValue + TENS.SeqValue + ONES.SeqValue) SeqValue
FROM(SELECT 0 SeqValue 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) ONES
CROSS JOIN(SELECT 0 SeqValue UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60 UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90) TENS
CROSS JOIN(SELECT 0 SeqValue UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300 UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600 UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900) HUNDREDS
) SEQ
) n
ON LENGTH(REPLACE(#Set1, ',' , '')) <= LENGTH(#Set1)-n.digit
ORDER BY n.digit
) t
WHERE NOT FIND_IN_SET(col, #set2);
which will return up to 1000 items in a single comma separated list

Rewrite to not include subquery in FROM?

A great fellow helped me with developing the following statement. However, in mySQL - I cannot save a view with a subquery in the FROM clause. Any suggestions o nhow to rewrite this so that it can be saved into a mySQL server?
SELECT t.idPatternMetadata, SUBSTRING_INDEX(SUBSTRING_INDEX(t.sKeywords, ',', n.n), ',', -1) color , count(*) as counts
FROM tblPatternMetadata t CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N 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) a
,(SELECT 0 AS N 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) b
ORDER BY n
) n
WHERE n.n <= 1 + (LENGTH(t.sKeywords) - LENGTH(REPLACE(t.sKeywords, ',', '')))
group by color
THANKS in advance!
One option is to create a table that contains the 100 integer values, and reference that table in the query.
CREATE TABLE n (n INT UNSIGNED PRIMARY KEY);
INSERT INTO n (n)
SELECT a.n + b.n * 10 + 1 n
FROM ( SELECT 0 AS n 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
) a
CROSS
JOIN ( SELECT 0 AS n 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
) b
ORDER BY 1;
Then rewrite your query to reference the table in place of the inline view:
SELECT t.idPatternMetadata, SUBSTRING_INDEX(SUBSTRING_INDEX(t.sKeywords, ',', n.n), ',', -1) AS color
, count(*) AS counts
FROM tblPatternMetadata t
JOIN n
ON n.n <= 1 + (LENGTH(t.sKeywords) - LENGTH(REPLACE(t.sKeywords, ',', '')))
GROUP BY color