0

I have this table in mysql:

DATE NAME MARK
2021-02-01 ALEX 7
2021-02-01 JOHN 5
2021-02-01 FRANK 4
2021-02-02 EVA 8
2021-02-02 ALICIA 5

How can I get a result similar to this:

DATE ALEX JOHN FRANK EVA ALICIA
2021-02-01 7 5 4
2021-02-02 8 5

It is Possible in Mysql?

Akina
  • 31,909
  • 5
  • 12
  • 21
  • Use dynamic SQL in stored procedure. – Akina Feb 10 '21 at 10:38
  • 2
    That's a sql anti-pattern. While rules are made to be broken, in principle it indicates you're trying to do something the wrong way, or in the wrong place (do this in presentation layers, not in data layers) – MatBailie Feb 10 '21 at 10:41
  • 1
    Seriously consider handling issues of data display in application code – Strawberry Feb 10 '21 at 14:11

1 Answers1

1

Create procedure

CREATE PROCEDURE pivot (tablename VARCHAR(64),
                        groupname VARCHAR(64),
                        pivotname VARCHAR(64),
                        valuename VARCHAR(64))
BEGIN
SELECT CONCAT('CREATE VIEW to_columnslist AS\n',
              'SELECT DISTINCT CONCAT(\'`\', `', pivotname,'`, \'` VARCHAR(255) path \\\'$."\', ', pivotname,', \'"\\\'\') line\n',
              'FROM ', tablename)
INTO @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DROP PREPARE stmt;
SELECT CONCAT(
'SELECT to_json.`', groupname,'`, parsed.*', '\n',
'FROM (SELECT `', groupname,'`, JSON_OBJECTAGG(`', pivotname,'`, `', valuename,'`) json_data', '\n',
'      FROM `', tablename,'`', '\n',
'      GROUP BY `', groupname,'`) to_json', '\n',
'CROSS JOIN JSON_TABLE( json_data,', '\n',
'                       "$" COLUMNS ( ', 
GROUP_CONCAT(line SEPARATOR ',\n                                     '),
' ) ) parsed'
) sql_text
INTO @sql
FROM to_columnslist;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DROP PREPARE stmt;
DROP VIEW to_columnslist;
END

and use it.

See fiddle

Akina
  • 31,909
  • 5
  • 12
  • 21
  • Thank you very much!!! Can i use secondary index for example date? – Alessandro La Ragione Feb 10 '21 at 13:04
  • Hi! it s works only with mysql 8? I got Mariadb and doesn t works. Br,Alessandro – Alessandro La Ragione Feb 10 '21 at 20:48
  • @AlessandroLaRagione You have tagged your question as MySQL-relative and have not specified its version - so I must assume that you use the most recent MySQL version. MariaDB (any version) and MySQL (prior to 8.0.14) cannot use this code. – Akina Feb 11 '21 at 04:54
  • Sorry this Is my fault. – Alessandro La Ragione Feb 11 '21 at 07:22
  • @AlessandroLaRagione I'll investigate. This will take some time. – Akina Feb 11 '21 at 13:52
  • @AlessandroLaRagione https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=7d06b1257fcc50077eb304f1e8c2f52d The problem source was in `NAME VARCHAR(6)` - the value `'John Jr.'` is longer than 6 symbols. – Akina Feb 11 '21 at 13:57
  • Ok i found problem but i don t know how to solve It. I add varchar(60) 'verify' field. So if i add an other field procedure doesn t works. Can you help me? BR,Alessandro – Alessandro La Ragione Feb 11 '21 at 16:59
  • @AlessandroLaRagione I cannot now, because I cannot guess your data. Create a fiddle with your real structure and data sample. – Akina Feb 11 '21 at 17:33
  • Ok if i have more than 10 values at same date It doesn t works... – Alessandro La Ragione Feb 11 '21 at 19:24
  • https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=334367b6707e072d76c5ff3802efdd3f – Alessandro La Ragione Feb 11 '21 at 19:24
  • @AlessandroLaRagione Now the source of the problem is server settings. By default the value of `@@group_concat_max_len` system variable is 1024, so the query text is truncated. Increase its value. – Akina Feb 11 '21 at 20:22
  • Ok i have increased value SET GLOBAL group_concat_max_len = 100000000. But It doesn t works – Alessandro La Ragione Feb 11 '21 at 22:39
  • @AlessandroLaRagione https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a5b399518942955702a5e05da11b6617 – Akina Feb 12 '21 at 06:31
  • Hi! It works! Thank you! It possible to have a result in a view? And It possible for example only update view only with new record? If i execute procedure each time It take a lot of time. – Alessandro La Ragione Feb 15 '21 at 06:44
  • @AlessandroLaRagione *It possible to have a result in a view?* You have a query text which gives needed result - nothing prevents to create a view with this query text. *update view only with new record?* Store the timestamp of view creation in some service table and compare it with maximal `updated_at` value, if the view is older then re-create it. – Akina Feb 15 '21 at 06:50
  • Thank you. I never used stored procedure...for me Is forse time....so...Can you help me? – Alessandro La Ragione Feb 15 '21 at 12:40
  • Ok i need to insert a where in pivot procedure...I have tried but i have some problems.... https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=4d81e7d6fdae9d538cd3d330a1024a67 – Alessandro La Ragione Feb 16 '21 at 09:06
  • Nobody Can help me? I Need filter by tagname and timestamp stored procedure – Alessandro La Ragione Feb 17 '21 at 06:51
  • Akina, Can you help me? – Alessandro La Ragione Feb 19 '21 at 07:30
  • @AlessandroLaRagione, the comment section is not intended for follow up questions. – trincot Mar 04 '21 at 09:07
  • If more than one concurrent client tries to use this solution, they will conflict. Each of them will try to create the `to_columnslist` view, but all but the first will lose and get an error. – Bill Karwin Mar 04 '21 at 16:03