MySQL UNION stored procedure pivot tables - mysql

I need to be able to Union the results of 3 Stored Procedures.
The Procedures are coded the same but produce different results.
I have tried creating temporary tables within each procedure and UNION ALL on those within another procedure, but it is not giving me the expected results.
Thank you.
DROP PROCEDURE IF EXISTS CONVERTOPCOLTOROWS;
DELIMITER $$
CREATE PROCEDURE CONVERTOPCOLTOROWS (IN n_seq INT)
BEGIN
SET #my_schema='femlinecycletime';
SET #my_table='table_seqcycletime';
SET #clause_where='`Seq`=';
SELECT GROUP_CONCAT(my_query
SEPARATOR ' UNION ALL ')
INTO #sql FROM
(SELECT
CONCAT('SELECT', QUOTE(COLUMN_NAME), ' AS `KEY`, `', COLUMN_NAME, '` AS `value` FROM `', #my_table,'`WHERE ', #clause_where, n_seq) my_query
FROM
(SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA` . `COLUMNS`
WHERE `TABLE_SCHEMA` = #my_schema
AND `TABLE_NAME` = #my_table
AND `COLUMN_NAME` BETWEEN 'OP02' AND 'OP90') AS `col1`) AS `col2`;
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
End;
$$
DELIMITER ;

Related

How to Create View or Table from Prepared Statement (Select Query)

I am trying to create View from the following prepared statement:
CREATE VIEW myview AS -- this line is not working
SELECT CONCAT(GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total FROM mydb.source_table' SEPARATOR '\n UNION ALL \n'),'\nORDER BY Total ASC')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'mydb'
AND TABLE_NAME = 'source_table'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
I am still confused with handling group_concat syntax.
I just need help on how to create View with the above prepared statement.
UPDATE 1: Stored procedure
As suggested by #nbk, I have to create into 5 stored procedures in single column to be able the data and use it to CREATE TABLE query. Here's the stored procedure version of the above codes.
CREATE DEFINER=`admin`#`%` PROCEDURE `sp_result`()
BEGIN
SELECT CONCAT(GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns FROM mydb.source_table' SEPARATOR '\n UNION ALL \n'), '\n LIMIT 0, 1 \n')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'mydb'
AND TABLE_NAME = 'source_table'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
Here's the result of this stored procedure:
+-----------+
| MyColumns |
+-----------+
| Abc |
+-----------+
In order this approach to be useful to me, I want the above result to be the one of the column of my CREATE TABLE query:
Here are my attempts but no luck:
First attempt: Separate Query
CREATE TABLE my_table AS SELECT id, name, mydb.sp_result() FROM source_table; -- Error Code: 1305. FUNCTION project_x.best_vendor1_name does not exist
Second attempt: Inserted at the last part of the stored procedure
CREATE TABLE my_table AS SELECT #sql FROM source_table; -- no effect
Here, I really do not know how CREATE TABLE using the stored procedure returned data.
UPDATE 2: Illustrate Encapsulation
CREATE DEFINER=`root`#`%` PROCEDURE `proc_column_sum`()
BEGIN
DROP TABLE IF EXISTS table2;
SELECT CONCAT('
CREATE TABLE table2 AS (',GROUP_CONCAT('
SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total
FROM testdb.products '
SEPARATOR '\n UNION ALL \n'), -- runtime syntax error somewhere here
'\n ORDER BY Total ASC)') -- missing closing single quote right after ASC
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb'
AND TABLE_NAME = 'products'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
You must put the CREATE TABLE in your prepared statement.
this example uses a temporary table only for demonstration purposes
CREATE DEFINER=`root`#`%` PROCEDURE `proc_column_sum`()
BEGIN
SELECT
CONCAT('CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS (',GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total FROM testdb.products ' SEPARATOR '\n UNION ALL \n'),'\nORDER BY Total ASC)')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb'
AND TABLE_NAME = 'products'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
you call it then
call proc_column_sum();
SELECT * FROM table2
But with this approach you have call every time the procedure to get the newest data.
I can' figure out, what went wrong in your query
CREATE DEFINER=`root`#`%` PROCEDURE `proc_column_sum`()
BEGIN
DROP TABLE IF EXISTS table2;
SELECT CONCAT('
CREATE TABLE IF NOT EXISTS table2 AS (',GROUP_CONCAT('
SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total
FROM testdb.products '
SEPARATOR '\n UNION ALL \n')
,'\nORDER BY Total ASC)')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb'
AND TABLE_NAME = 'products'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END

MySQL : How to dynamically call stored procedures when inserting new row in table

I have a query that dynamically convert rows into column when inserting new row in table. However, every time I inserting new row in table I need to call the stored procedure to show the output call bian_test_db.new_procedure();. How can I make it automatically show the new insert data in view without calling the procedure.
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
SET SESSION group_concat_max_len = 1000000;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'ifnull(SUM(case when itemname = ''',
itemname,
''' then itemvalue end),0) AS ',
itemname
)
) INTO #sql
FROM
bian_test_db.history;
SET #sql = CONCAT('CREATE OR REPLACE view testing as SELECT user_id, ', #sql, '
FROM bian_test_db.history
GROUP BY user_id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
First create below procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
SET SESSION group_concat_max_len = 1000000;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'ifnull(SUM(case when itemname = ''',
itemname,
''' then itemvalue end),0) AS ',
itemname
)
) INTO #sql
FROM
bian_test_db.history;
SET #sql = CONCAT('CREATE OR REPLACE view testing as SELECT user_id, ', #sql, '
FROM bian_test_db.history
GROUP BY user_id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
And then create below trigger,which call above Procedure from it.
DELIMITER $$
CREATE TRIGGER CHANGE_ROW_YOUR_TABLE
AFTER INSERT ON YOUR_TABLE
FOR EACH ROW
BEGIN
call new_procedure;
END$$
DELIMITER ;
Hope this will help you.
You could use a trigger
CREATE TRIGGER your_trigger_name AFTER INSERT ON your_table
FOR EACH ROW
BEGIN
.... your code
END
see https://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html and https://dev.mysql.com/doc/refman/5.7/en/create-trigger.html

Error in creating temporary table in mysql

I am facing difficulty in creating temporary table in mysql.
I have a stored procedure i am creating some sql statement i need to create the sql statement output as a temporary table in my sql. Here is my procedure. any body help me please?
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN workspaceid = ''',
workspaceid,
''' then "''''" ELSE NULL end) AS ',
CONCAT('`',workspaceid,'`')
)
) INTO #sql
FROM sms.hotelings;
SET #sql = CONCAT('SELECT t.Time, ', #sql, '
FROM sms.hotelings h, sms.hotelingtime t
GROUP BY t.Time');
-- PREPARE stmt FROM #sql;
-- EXECUTE stmt;
-- DEALLOCATE PREPARE stmt;
CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS #sql;
select * from table2
drop temporary table table2;
END
I want to create a temporary table using my #sql statement.
Thanks in advance.
You have to use PREPARE if you want to use a dynamic statement
SET #sql = CONCAT('CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS SELECT t.Time, ', #sql, '
FROM sms.hotelings h, sms.hotelingtime t
GROUP BY t.Time');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT * FROM table2;
DROP TEMPORARY TABLE table2;

MySql Stored Procedure and Comma Separated Varchar with In Statement

I'm trying to create a stored procedure which will take a comma separated list as a value and push that into a select statement with an IN clause. I'm aware of find_in_set which works, but does have a performance overhead. I've also trialled a prepare statement but the problem remains.
My Example:
My parameter is sp1 and contains the value: 'valuex, valuey, valuez'.
BEGIN
set #sql = concat('select * from tablename WHERE assignedTo in (', sp1, ')');
PREPARE q FROM #sql;
execute q;
END
As expected, this throws an error since SQL will treat the value as column names. My question is how do I achieve: 'valuex','valuey','valuez' FROM 'valuex, valuey, valuez'?
You can use replace function:
BEGIN
set #sql = concat("select * from tablename WHERE assignedTo in ('", replace(sp1,",","','"), "')");
PREPARE q FROM #sql;
execute q;
END
An option is:
DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_test`$$
CREATE PROCEDURE `sp_test`(`sp1` VARCHAR(50))
BEGIN
SET `sp1` := REPLACE(REPLACE(`sp1`, ', ', ','), ',', '\',\'');
SET #`query` := CONCAT('SELECT `column0`, `column1` FROM `tablename` WHERE `assignedTo` IN (\'', `sp1`, '\');');
PREPARE `stmt` FROM #`query`;
EXECUTE `stmt`;
DEALLOCATE PREPARE `stmt`;
END$$
DELIMITER ;
CALL `sp_test`('valuex, valuey, valuez');
-- SELECT `column0`, `column1` FROM `tablename` WHERE `assignedTo` IN ('valuex','valuey','valuez');

How to select from data with variable Database and Table

Is there any way to select from a variable table name database name and value?
I'm trying to a check the column value is exist from the below way. I forced do this way because the table name and column names and values are variable...
This is used in a Stored Procedure File.
I want something like:
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA= 'database1'
AND TABLE_NAME= 'table1'
AND COLUMN_NAME = 'clmn_id_fk'
AND 'database1.table1.clmn_id_fk'=2218
I am not able to find a result.
You can take inspiration from a stored procedure as shown below. Change all that is necessary to achieve the solution you want, it is very important to include all the relevant restrictions and validations.
/* CODE FOR DEMONSTRATION PURPOSES */
DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_check`$$
CREATE PROCEDURE `sp_check`(`p_table_schema` VARCHAR(64), `p_table_name` VARCHAR(64), `p_column_name` VARCHAR(64), `p_value` INT)
BEGIN
IF EXISTS (SELECT NULL
FROM `information_schema`.`columns`
WHERE `table_schema` = `p_table_schema` AND
`table_name` = `p_table_name` AND
`column_name` = `p_column_name`) THEN
SET #qry := CONCAT('SELECT IF(COUNT(`', `p_column_name`, '`), 1, 0) AS `EXISTS` FROM `', `p_table_schema`, '`.`', `p_table_name`, '` WHERE `', `p_column_name`, '` = ', `p_value`);
PREPARE stmt FROM #qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
ELSE
SELECT 0 AS `EXISTS`;
END IF;
END$$
DELIMITER ;
CALL `sp_check`('database1', 'table1', 'clmn_id_fk', 2218);