In MySQL, given the following table where Tags is a column that contains comma separated strings
Id Name Salary Tags
----------------------------
1 James 5000 Sales, Marketing
2 John 4000 Sales, Finance
3 Sarah 3000 HR, Marketing, Finance
How could we get sum(Salary) for each word/tag in Tags? so the result would look like this?
Tag TotalSalary
------------------------
Sales 9000
Marketing 8000
Finance 7000
HR 3000
Any help would be very appreciated. Thank you!
While I'd highly recommend normalizing your data structure and not store comma delimited lists, here's one handy approach utilizing a "numbers" table:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(tags, ',', n.n), ',', -1) value, sum(salary)
FROM tags 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(tags) - LENGTH(REPLACE(tags, ',', '')))
GROUP BY SUBSTRING_INDEX(SUBSTRING_INDEX(tags, ',', n.n), ',', -1)
SQL Fiddle Demo
This leverages substring_index and can support up to 100 delimited items - easy to adjust as needed. I've used this approach several times which works quite well -- I first saw it used in this post.
Related
How to split the string and grouping them by splited token?
I want to get that grouping splited token's each count.
I have a varchar column and it store a string which can split by ',' .
below is the row data of the column. (column name is LogData)
[LogData]
1,2,3,4
1,3,1,9
2,1,3
6,2
And then i want to show(select) like below.
[token] [count]
1 : 4
2 : 3
3 : 3
4 : 1
6 : 1
9 : 1
If possible, then may i have a answer about this with some explanation? (I'm not skilled in db)
Using the and adapting the comment from undefined_variable the correct query looks like this:
SELECT value,COUNT(*) FROM
(SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t0.logdata, ',', n.n), ',', -1) value
FROM t0 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(t0.logdata) - LENGTH(REPLACE(t0.logdata, ',', '')))
ORDER BY value) nt0 GROUP BY value
I want to a MySQL query to select the records separately from following table
ID AgentID Name Return Date
1 1,2,3 A 2016-05-22,2016-02-1,2016-1-15
2 2,4 B 2016-03-22,2016-04-1
Expecting Answer
ID AgentID Name Return Date
1 1 A 2016-05-22
1 2 A 2016-02-1
1 3 A 2016-1-15
2 2 B 2016-03-22
2 4 B 2016-04-1
You can use MySQL SUBSTRING_INDEX(). It will return the sub-string from the given comma separated string before a specified number of occurrences of the delimiter.
Try this, It seems to work fine:
SELECT ID
,SUBSTRING_INDEX(SUBSTRING_INDEX(t.AgentID, ',', n.n), ',', -1) Agent
,Name
,SUBSTRING_INDEX(SUBSTRING_INDEX(t.Return_Date, ',', n.n), ',', -1) Return_Date
FROM table1 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.Return_Date) - LENGTH(REPLACE(t.Return_Date, ',', '')))
ORDER BY ID;
Check this..
SQL Fiddle HERE
For further Study go on MySQL Split String Function
if your values in tblA and you want to insert into tblB than query like this
insert into tblB (date) select date from tblA;
INSERT INTO second_table (
Field_1,
Field_2,
Field_3)
SELECT Field_1,
Field_2,
Field_3
FROM first_table;
I want to a MySQL query to select the records separately from following table
ID AgentID Name Return Date
1 1,2,3 A 2016-05-22,2016-02-1,2016-1-15
2 2,4 B 2016-03-22,2016-04-1
Expecting Answer
ID AgentID Name Return Date
1 1 A 2016-05-22
1 2 A 2016-02-1
1 3 A 2016-1-15
2 2 B 2016-03-22
2 4 B 2016-04-1
You can use MySQL SUBSTRING_INDEX(). It will return the sub-string from the given comma separated string before a specified number of occurrences of the delimiter.
Try this, It seems to work fine:
SELECT ID
,SUBSTRING_INDEX(SUBSTRING_INDEX(t.AgentID, ',', n.n), ',', -1) Agent
,Name
,SUBSTRING_INDEX(SUBSTRING_INDEX(t.Return_Date, ',', n.n), ',', -1) Return_Date
FROM table1 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.Return_Date) - LENGTH(REPLACE(t.Return_Date, ',', '')))
ORDER BY ID;
Check this..
SQL Fiddle HERE
For further Study go on MySQL Split String Function
if your values in tblA and you want to insert into tblB than query like this
insert into tblB (date) select date from tblA;
INSERT INTO second_table (
Field_1,
Field_2,
Field_3)
SELECT Field_1,
Field_2,
Field_3
FROM first_table;
There is a table(Course Interests) which has all the values in one cell. But those values are just ids and I want to join them with another table(Course) so I can know their names.
Course Interests:
MemberID MemberName CoursesInterested
-------------- --------------------- --------------
1 Al 1,4,5,6
2 A2 3,5,6
Course Table:
CourseId Course
-------------- ---------------------
1 MBA
2 Languages
3 English
4 French
5 Fashion
6 IT
Desired Output:
MemberID MemberName CoursesInterested
-------------- --------------------- --------------
1 Al MBA,French,Fashion,IT
2 A2 English,Fashion,IT
I would like to do a SQL query in MySql that can help me to extract the desired output. I know how to do it in the opposite way(join values to one cell), but I've struggling on seek a way to separate the ids and do a cross-join into another table.
I'll appreciate any help from the community. Thanks
Use FIND_IN_SET to search for something in a comma-delimited list.
SELECT i.MemberID, i.MemberName, GROUP_CONCAT(c.Course) AS CoursesInterested
FROM CourseInterests AS i
JOIN Course AS c ON FIND_IN_SET(c.CourseId, i.CoursesInterested)
However, it would be better to create a relation table instead of storing the courses in a single column. This type of join cannot be optimized using an index, so it will be expensive for a large table.
Try this Out:
SELECT MemberID,MemberName,Group_Concat(C.Course) from
(
SELECT MemberID,MemberName,SUBSTRING_INDEX(SUBSTRING_INDEX(t.CoursesInterested, ',', n.n), ',', -1) value
FROM Table1 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.CoursesInterested) - LENGTH(REPLACE(t.CoursesInterested, ',', '')))
ORDER BY MemberID,value
) T JOIN course C ON T.value = C.CourseId
Group By MemberID,MemberName
Fiddle Demo
Output:
MemberID MemberName CoursesInterested
-------------- --------------------- --------------
1 Al MBA,French,Fashion,IT
2 A2 English,Fashion,IT
This question already has answers here:
MySQL: Split comma separated list into multiple rows
(4 answers)
Closed 9 years ago.
I have a column with a variable number of comma seperated values:
somethingA,somethingB,somethingC
somethingElseA, somethingElseB
And I want the result to take each value, and create a row:
somethingA
somethingB
somethingC
somethingElseA
somethingElseB
How can I do this in SQL (MySQL)?
(I've tried googling "implode" and "lateral view", but those don't seem to turn up related questions. All the related SO questions are trying to do much more complicated things)
You can do it with pure SQL like this
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.values, ',', n.n), ',', -1) value
FROM table1 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.values) - LENGTH(REPLACE(t.values, ',', '')))
ORDER BY value
Note: The trick is to leverage tally(numbers) table and a very handy in this case MySQL function SUBSTRING_INDEX(). If you do a lot of such queries (splitting) then you might consider to populate and use a persisted tally table instead of generating it on fly with a subquery like in this example. The subquery in this example generates a sequence of numbers from 1 to 100 effectively allowing you split up to 100 delimited values per row in source table. If you need more or less you can easily adjust it.
Output:
| VALUE |
|----------------|
| somethingA |
| somethingB |
| somethingC |
| somethingElseA |
| somethingElseB |
Here is SQLFiddle demo
This is how the query might look with a persisted tally table
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.values, ',', n.n), ',', -1) value
FROM table1 t CROSS JOIN tally n
WHERE n.n <= 1 + (LENGTH(t.values) - LENGTH(REPLACE(t.values, ',', '')))
ORDER BY value
Here is SQLFiddle demo