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
Related
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)
I'm migrating an old database data to a new one, and they used to store telephone numbers in the following format:
Example 1:
41.9044-9082;41.9044-9661;41.9851-9862;41.9984-0393;41.3399-9169;41.3997-7999;
Example 2:
41.3369-0102;41.8928-5992;
No telephones(empty):
;
How can I split these single VARCHAR fields with many values, and insert them separately?
Table example of how it is:
|#id_tel#|### number ####|#|client_id|#|
|# 1 #|111163;3554353;|#| 2 |#|
|# 2 #|222222; |#| 3 |#|
|# 3 #|; |#| 4 |#|
Table example of how I would like it to be:
|#id_tel#|### number ####|#|client_id|#|
|# 1 #|111163 |#| 2 |#|
|# 2 #|3554353 |#| 2 |#|
|# 3 #|222222 |#| 3 |#|
You could do that with nested calls of SUBSTRING_INDEX() and a numbers table. In my example I create the numbers table on the fly for up to 100 numbers.
Assuming a table old_tel with following CREATE TABLE statement:
CREATE TABLE old_tel (
id_tel INT,
`number` VARCHAR(200),
client_id INT
);
you get the splitted numbers with the client_id with this query:
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) value,
client_id
FROM
old_tel
CROSS JOIN (
SELECT
1 + a.N + b.N * 10 AS 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 <= LENGTH(`number`) - LENGTH(REPLACE(`number`, ';', ''))
AND
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) <> ''
ORDER BY
client_id, SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1);
Assuming your new telephone numbers table looks nearly the same:
CREATE TABLE new_tel (
id_tel INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`number` VARCHAR(200),
client_id INT
);
you can fill this table with this simple INSERT statement using the first query:
INSERT INTO new_tel (`number`, client_id)
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) value,
client_id
FROM
old_tel
CROSS JOIN (
SELECT
1 + a.N + b.N * 10 AS 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 <= LENGTH(`number`) - LENGTH(REPLACE(`number`, ';', ''))
AND
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) <> ''
ORDER BY
client_id, SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1);
Explanation
The inner subselect with the UNION ALL creates on the fly a numbers table. We restrict this on the number of substrings in the number column and filter out empty values.
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) value
cuts out the n-th number that is separated by semicolon.
See it working in this Demo
**Note: ** This is very fast by avoiding agonizing row by row inserts.
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
I do an update in a table row by row:
UPDATE table
SET col = $value
WHERE id = $id
Now if I update e.g. 10000 records each record gets the $value but it does not really matter which $id gets which $value. The only requirement I have is that all the records I am updating end up with a $value.
So how could I convert this update to something like
UPDATE table
SET col ?????? what here from a $value_list???
WHERE id IN ($id_list)
I.e. pass the list ids and somehow the values and that range of ids get a value
Let's assume you've got two comma separated lists of your ids and your values with the same count of items. Then you could do your update with statements like those:
-- the list of the ids
SET #ids = '2,4,5,6';
-- the list of the values
SET #vals = '17, 73,55, 12';
UPDATE yourtable
INNER JOIN (
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(t.ids, ',', n.n), ',', -1) id,
SUBSTRING_INDEX(SUBSTRING_INDEX(t.vals, ',', n.n), ',', -1) val
FROM (SELECT #ids as ids, #vals as vals) t
CROSS JOIN (
-- build for up to 1000 separated values
SELECT
1 + a.N + b.N * 10 + c.N * 100 AS 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
,(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) c
ORDER BY n
) n
WHERE n <= (1 + LENGTH(t.ids) - LENGTH(REPLACE(t.ids, ',', '')))
) t1
ON
yourtable.id = t1.id
SET
yourtable.val = t1.val;
Explanation
The inner series of UNIONs builds a table with the numbers from 1 to 1000. You should be able to expand this mechanism to your needs:
-- build for up to 1000 separated values
SELECT
a.N + b.N * 10 + c.N * 100 + 1 AS 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
,(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) c
ORDER BY n
We use this numbers to get the items out of our lists with the nested SUBSTRING_INDEX call
SUBSTRING_INDEX(SUBSTRING_INDEX(t.ids, ',', n.n), ',', -1) id,
SUBSTRING_INDEX(SUBSTRING_INDEX(t.vals, ',', n.n), ',', -1) val
The WHERE clause get the number of items in (ok only one of the two) lists:
WHERE n <= (1 + LENGTH(t.ids) - LENGTH(REPLACE(t.ids, ',', '')))
Because we've got one occurence of the separator less, we add 1 to the difference in length of the list with the separator and the length of the list without all occurrences of the separator.
Then we do the UPDATE with a JOIN operation on the id values in the outer UPDATE statement.
See it working in this fiddle.
Believe me: This is much faster than agonizing row-by-row update.
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