Multiple group_concat - mysql

I am in the process of planning a database for a mysql project and think I need to get this solved before I go any further.
CREATE TABLE ResultsTbl (
EventID INTEGER,
MatchNumber INTEGER (9),
TeamNumber int,
IndividualName CHAR (100),
Result char (4)
);
INSERT INTO ResultsTbl VALUES (1,1,1,'individual 1','W');
INSERT INTO ResultsTbl VALUES (1,1,1,'individual 2','W');
INSERT INTO ResultsTbl VALUES (1,1,2,'individual 3','L');
INSERT INTO ResultsTbl VALUES (1,1,2,'individual 4','L');
INSERT INTO ResultsTbl VALUES (1,1,3,'individual 5','L');
INSERT INTO ResultsTbl VALUES (1,1,3,'individual 6','L');
INSERT INTO ResultsTbl VALUES (1,2,1,'individual 7','W');
INSERT INTO ResultsTbl VALUES (1,2,2,'individual 8','L');
INSERT INTO ResultsTbl VALUES (1,3,1,'individual 9','W');
INSERT INTO ResultsTbl VALUES (1,3,1,'individual 10','W');
INSERT INTO ResultsTbl VALUES (1,3,2,'individual 11','L');
INSERT INTO ResultsTbl VALUES (1,3,2,'individual 12','L');
So I have a table which holds data for matches. I need the end result to have one cell for each MatchNumber where the Result = 'W' and one where the Result = 'L', but I need the IndividualNames on the same teams concatenated with a "&". I also need the teams concatenated with a ",".
For the example above, the desired result needs to be as follows:
MatchNumber | Winners | Losers
1 | Individual 1 & individual 2 | individual 3 & individual 4, individual 5 & individual 6
2 | individual 7 | individual 8
3 | individual 9 & individual 10 | individual 11 & individual 12
So on MatchNumber 1 we have one team in the winners but 2 teams in the losers. The individual within the same teams are concatenated with a "&", and the different teams are concatenated with a ",". Match 2 only has 1 individual on each team, so there are no special characters needed. Match 3 has 1 team of 2 individuals on both the winners and losers, so they are concatenated with a "&" with no need for a ",".
I would love to write what I have failed on but I just can't get any where near what I need to do. I have looked down the road of a group_concat on the teams, then a group_concat on the result, but I can't figure it out.
I wanted to get this dealt with before processing all of the data, so if the table structures need changing to get this done then I am open to suggestions.
Thanks for any help or advice anyone can give.

You need a first set of results by match number, team, and winning type
You need second set of result by match number and winning type
select
MatchNumber,
group_concat( Winners ) Winners,
group_concat( Losers ) Losers
from
(
select
MatchNumber,
TeamNumber,
case Result when 'W'
then group_concat(IndividualName separator '&') end Winners,
case Result when 'L'
then group_concat(IndividualName separator '&') end Losers,
group_concat(Result separator '&') r
from
Resultstbl
group by
MatchNumber, TeamNumber
) g
group by MatchNumber

Give this a bash:
select MatchNumber,
group_concat(Winners order by TeamNumber),
group_concat(Losers order by TeamNumber)
from
(
select MatchNumber,TeamNumber,
group_concat(case when Result = 'W' then IndividualName end SEPARATOR " & ") as Winners,
group_concat(case when Result = 'L' then IndividualName end SEPARATOR " & ") as Losers
from ResultsTbl
group by MatchNumber, TeamNumber
) t
group by MatchNumber
;

Related

how to use concat, like and subconsultas with where?

SELECT asset_tag.asset_id, LEFT(asset_tag,SUBSTRING(asset_tag)-1 AS 'ETIQ'
from (SELECT DISTINCT S2.asset_id + ',' AS etiquetas
(SELECT S1.tag_id
FROM asset_tag AS S1
WHERE S1.tag_id
ORDER BY S1.tag_id
FOR XML PATH (''),TYPE
).VALUE('TEXT(1)`[1]','ninteger(MAX')[aset_tag] FROM asset_tag AS S2 ) asset_tag;
I have to group by asset and the asset 1 have in one column 1,2,3,4,5 or the tag that it have
how to use heidisql functions, on dbforge? I know but here not I use heidisql version 12. and is my first time working with this
The objective is that the source table that has two columns, group by column 1 and that a new column indicate separated by commas what column 1 has in column 2 (of origin).
columna 1 - 1 1 2 2 3 3 4 4
columna 2 - a b c a d a f g
and in a new column or table 1 - a b / 2 - b c
I see this answer on this page: https://stackoverflow.com/a/545672/20100117 But i donĀ“t know what mean "st1" or [text()] the alias?
SELECT Main.SubjectID,
LEFT(Main.Students,Len(Main.Students)-1) As "Students" FROM
(
SELECT DISTINCT ST2.SubjectID,
(
SELECT ST1.StudentName + ',' AS [text()]
FROM dbo.Students ST1
WHERE ST1.SubjectID = ST2.SubjectID
ORDER BY ST1.SubjectID
FOR XML PATH (''), TYPE
).value('text()[1]','nvarchar(max)') [Students]
FROM dbo.Students ST2
) [Main]
If you use HeidiSQL, you can use the completion proposal to help finding the right syntax for the various functions. Just type some first characters and press Ctrl+Space:
Here's a basic example of how SUBSTRING() works:
SELECT SUBSTRING(name, 2, 3) FROM mytable;
How to concatenate rows of the same column in PostgreSQL?
Given that you want to concatenate rows of the same column, and not different columns (which is what you do when using CONCAT_WS()), what you would really be looking for is to use the ARRAY_AGG aggregation function within the ARRAY_TO_STRING function.
Documentation: https://www.postgresql.org/docs/13/functions-array.html
solution:
SELECT
a.asset_id, ARRAY_TO_STRING(ARRAY_AGG(a.tag_id), ',') AS etiqueta
FROM public.asset_tag AS a
GROUP BY a.asset_id;
Result:
on asset_id 1 | 1,3,5 tag_id
on asset_id 6 | 1,2 tag_id
If you insert this:
CREATE TABLE asset_tag ( asset_id INT,tag_id INT);
INSERT INTO asset_tag VALUES (1,1);
INSERT INTO asset_tag VALUES (1,3);
INSERT INTO asset_tag VALUES (1,5);
INSERT INTO asset_tag VALUES (6,1);
INSERT INTO asset_tag VALUES (6,2);
thanks to the person who gave me this answer .

counting comma separated values mysql-postgre

I have a column called "feedback", and have 1 field called "emotions". In those emotions field, we can see the random values and random length like
emotions
sad, happy
happy, angry, boring
boring
sad, happy, boring, laugh
etc with different values and different length.
so, the question is, what's query to serve the mysql or postgre data:
emotion
count
happy
3
angry
1
sad
2
boring
3
laugh
1
based on SQL: Count of items in comma-separated column in a table we could try using
SELECT value as [Holiday], COUNT(*) AS [Count]
FROM OhLog
CROSS APPLY STRING_SPLIT([Holidays], ',')
GROUP BY value
but it wont help because that is for sql server, not mysql or postgre. or anyone have idea to translation those sqlserver query to mysql?
thank you so much.. I really appreciate it
Using Postgres:
create table emotions(id integer, emotions varchar);
insert into emotions values (1, 'sad, happy');
insert into emotions values (2, 'happy, angry, boring');
insert into emotions values (3, 'boring');
insert into emotions values (4, 'sad, happy, boring, laugh');
select
emotion, count(*)
from
(select
trim(regexp_split_to_table(emotions, ',')) as emotion
from emotions) as t
group by
emotion;
emotion | count
---------+-------
happy | 3
sad | 2
boring | 3
laugh | 1
angry | 1
From String functions regexp_split_to_table will split the string on ',' and return the individual elements as rows. Since there are spaces between the ',' and the word use trim to get rid of the spaces. This then generates a 'table' that is used as a sub-query. In the outer query group by the emotion field and count them.
Try the following using MySQL 8.0:
WITH recursive numbers AS
(
select 1 as n
union all
select n + 1 from numbers where n < 100
)
,
Counts as (
select trim(substring_index(substring_index(emotions, ',', n),',',-1)) as emotions
from Emotions
join numbers
on char_length(emotions) - char_length(replace(emotions, ',', '')) >= n - 1
)
select emotions,count(emotions) as counts from Counts
group by emotions
order by emotions
See a demo from db-fiddle.
The recursive query is to generate numbers from 1 to 100, supposing that the maximum number of sub-strings is 100, you may change this number accordingly.
I've used MySQL 8.0, the query has no string limits. (Thanks to Ahmed for the intuition on recursive clause)
WITH RECURSIVE cte AS (
SELECT ( LENGTH(REGEXP_REPLACE(emotions, ' ?[A-z]+ ?', ''))+1) AS n, emotions AS subs
FROM feedback
UNION ALL
SELECT n-1 AS n, ( SUBSTRING_INDEX(subs, ', ', n-1) ) AS subs
FROM cte
HAVING n>0
)
SELECT SUBSTRING_INDEX(subs, ', ', -1) AS emotions, COUNT(subs) AS cnt
FROM cte
GROUP BY emotions

MySQL - How can I group music together when the names are similar?

I would like to be able to return a single line when the name of some musics are the same or similar, as for example this case:
music with similar names
You can see that the names are the same with an extension like " - JP Ver." or something like that, I would like to be able to group them in one row with the first column incrementing the whole.
My current request to return these lines is as follows:
select count(id) number, name, sec_to_time(floor(sum(duration) / 1000)) time
from track
where user_id = 'value'
group by name, duration
order by number desc, time desc;
I would like to get a result like this
Thank you for reading and responding! I wish you all a good day!
Try:
SELECT COUNT(name) no,
TRIM(SUBSTRING_INDEX(name, '-', 1)) namee
FROM track
GROUP BY namee
Example: https://onecompiler.com/mysql/3xt3bfev6
Use GROUP_CONCAT
Here is a proof of concept script. You can add your other columns. I have grouped by the first 4 letters. You will probably want to use more.
CREATE TABLE track (
idd INT,
nam CHAR(50),
tim INT
);
INSERT INTO track VALUES (1,'Abba 1',5);
INSERT INTO track VALUES (2,'Abba 2',6);
INSERT INTO track VALUES (3,'Beta 1',12);
INSERT INTO track VALUES (4,'Beta 4',8);
SELECT
LEFT(nam,4) AS 'Group',
COUNT(idd) AS 'Number',
GROUP_CONCAT(DISTINCT idd ORDER BY idd ASC SEPARATOR ' & ') AS IDs,
GROUP_CONCAT(DISTINCT nam ORDER BY nam ASC SEPARATOR ', ') AS 'track names',
SUM(tim) AS 'total time'
FROM track
GROUP BY LEFT(nam,4);
DROP TABLE track;
Output
Group Number IDs track names total time
Abba 2 1 & 2 Abba 1, Abba 2 11
Beta 2 3 & 4 Beta 1, Beta 4 20

SQL max of multiple columns in pivot table

How can you find the max of several columns that are created in a pivot table using a SQL Server 2008 pivot table query?
Given:
create table ElectionResults_test
(
Total_Votes int,
Precinct_Name varchar(50),
Candidate_Name varchar(50)
)
insert into ElectionResults_test values (4,'CP01', 'DOUG')
insert into ElectionResults_test values (2,'CP02', 'DOUG')
insert into ElectionResults_test values (2,'CP01', 'LATHE')
insert into ElectionResults_test values (4,'CP02', 'LATHE')
SELECT Precinct_Name as ConsPrecinct_Name, 'DOUG' AS Candidate1, [DOUG] AS NumVotes1,
'LATHE' AS Candidate2, [LATHE] AS NumVotes2, 'Needs Data' as WinningCandidate FROM
(Select Total_Votes, Precinct_Name, Candidate_Name from [ELECTIONRESULTS_test])
as SourceTable pivot (sum(Total_Votes) for Candidate_Name in ([DOUG], [LATHE])) as PivotTable
The select statement above has the following output:
ConsPrecinct_name Candidate1 NumVotes1 Candidate2 NumVotes2 Winning Candidate
CP01 DOUG 4 LATH 2 Needs Data
CP01 DOUG 2 LATH 4 Needs Data
The goal is to have the 'Winning Candidate' field populated with the candidate name that has the most votes in the corresponding NumVotes field.
To deal with 8 way contests more easily you can use CROSS APPLY and VALUES, you may also want a GROUP BY as you haven't said how ties will be handled (this will return multiple rows for each winner)
SELECT Precinct_Name AS ConsPrecinct_Name,
'DOUG' AS Candidate1,
[DOUG] AS NumVotes1,
'LATHE' AS Candidate2,
[LATHE] AS NumVotes2,
WinningCandidate.name AS WinningCandidate
FROM (SELECT Total_Votes,
Precinct_Name,
Candidate_Name
FROM ElectionResults_test) AS SourceTable PIVOT (SUM(Total_Votes) FOR
Candidate_Name IN ([DOUG], [LATHE])) AS PivotTable
CROSS APPLY (SELECT CASE
WHEN COUNT(*) = 1 THEN MAX(name)
ELSE 'Tie'
END AS name
FROM (SELECT TOP 1 WITH TIES name
FROM (VALUES('DOUG', [DOUG]),
('LATHE', [LATHE])) Y(name, votes)
ORDER BY votes DESC) T)AS WinningCandidate
Try a CASE statement:
CASE WHEN [DOUG] > [LATHE] THEN 'DOUG'
WHEN [DOUG] < [LATHE] THEN 'LATHE'
ELSE 'No winner'
END AS WinningCandidate
If it's only a few fields you can use a CASE statement:
...
CASE WHEN NumVotes1 > NumVotes2 THEN Candidate1
WHEN NumVotes2 > NumVotes1 THEN Candidate2
ELSE 'TIE' END as WinningCandidate

MySQL String Comparison with Percent Output (Position Very Important

I am trying to compare two entries of 6 numbers, each number which can either can be zero or 1 (i.e 100001 or 011101). If 3 out of 6 match, I want the output to be .5. If 2 out of 6 match, i want the output to be .33 etc.
Note that position matters. A match only occurs when both entries have a 1 in the first position, both have a 0 in the second position etc.
Here are the SQL commands to create the table
CREATE TABLE sim
(sim_key int,
string int);
INSERT INTO sim (sim_key, string)
VALUES (1, 111000);
INSERT INTO sim (sim_key, string)
VALUES (2, 101101);
My desired output to compare the two strings, which share 50% of the characters, and output 50%.
Is it possible to do this sort of comparison in SQL? Thanks in advance
Have a look at this example.
CREATE TABLE sim (sim_key int, string int);
INSERT INTO sim (sim_key, string) VALUES (1, 111000);
INSERT INTO sim (sim_key, string) VALUES (2, 101101);
select a.string A, b.string B,
sum(case when Substring(A.string,Pos,1) = Substring(B.string,Pos,1) then 1 else 0 end) Matches,
count(*) as RowCount,
(sum(case when Substring(A.string,Pos,1) = Substring(B.string,Pos,1) then 1 else 0 end) /
count(*) * 100.0) as PercentMatch
from sim A
cross join sim B
inner join (
select 1 Pos union all select 2 union all select 3
union all select 4 union all select 5 union all select 6) P
on P.Pos between 1 and length(A.string)
where A.sim_key= 1 and B.sim_key = 2
group by a.string, b.string
It is crude and probably included more than required but shows how it can be done. It is better to create a numbers table with just numbers from 1 to 1000 or so, that can be used repeatedly in many queries where a number sequence is required. Such a table will replace the (select .. union virtual table used in the inner join)
Instead of keeping 10010101 as integer convert this binary version to true integer when compare use bit logic AND, result convert to binary and count '1' to how many match...
for convert: http://dev.mysql.com/doc/refman/5.5/en/binary-varbinary.html
for compare: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html bitwise AND
...