Mysql Pivot rows to columns - mysql

I have a table of data which some of data looks like below.
Table name Uk_Small_Stage1
name created 1m
IA UK Smaller Companies 17/10/2017 3.9
Jupiter UK Smaller Companies I Acc 17/10/2017 6.96
Old Mutual UK Smaller Companies Focus R Inc GBP 17/10/2017 2.19
TB Amati UK Smaller Companies B Acc 17/10/2017 4.85
TM Cavendish AIM B 17/10/2017 2.34
I want to pivot the table to look like
Created IA UK Smaller Companies Jupiter UK Smaller Companies I Acc Old Mutual UK Smaller Companies Focus R Inc GBP
17/10/2017 3.9 6.96 2.19
(a column should appear for each row against the field "name".
The Uk_Small_Stage1 has multiple records for each date.
I am trying to use the code below which should dynamically build and execute the pivot but am getting mysql errors.
Could any one help please?
SET group_concat_max_len=2048;
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(name = ''',
name,
''', 1m, NULL)) AS ‘,
CONCAT("`”,name,"`")
)
)
) INTO #sql
FROM UK_Small_Stage1;
SET #sql = CONCAT('SELECT created, ', #sql, ' FROM UK_Small_Stage1 GROUP BY created’);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Latest code
SET group_concat_max_len=2048;
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(name = ''',
name,
''', 1m, NULL)) AS ‘,
CONCAT(''',name,''')
)
)
) INTO #sql
FROM UK_Small_Stage1;
SET #sql = CONCAT('SELECT created, ', #sql, ' FROM UK_Small_Stage1 GROUP BY created’);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Related

How to make a pivot like sql result [duplicate]

I have following tables
demographic_categories
demographic_id demographic_name
1 color
2 age_group
project_tests
test_id group_id project_id
1 1 1
2 1 1
test_demographic_requirements
test_id project_id demgraphic_id demographic_value
1 1 1 blue
1 1 2 young
2 1 1 green
2 1 2 middle
And I need a query which would give me following result :
test_id group_id color age_group
1 1 blue young
2 1 green middle
I guess we need to use concept of pivot table to get the result, but I am unable to. And I demographic categories can we might be same they tend to change so I need something dynamic so what would be the best way to do it ?
I have tried doing the following based of previous similar questions but it doesn't seems to work for me, here is what I have tried:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when dc.demographic_name = ''',
demographic_name,
''' then trd.demographic_value end) AS ',
replace(demographic_name, ' ', '')
)
) INTO #sql
from demographic_categories;
SET #sql = CONCAT('SELECT pt.test_id, pt.group_id,
', #sql,'
from test_requirement_demographic trd
LEFT JOIN demographic_categories dc ON trd.demographic_id = dc.demographic_id
LEFT JOIN project_tests pt ON pt.test_id = trd.test_id and project_id =1
group by pt.test_id;');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Your dynamic SQL is just fine except for one thing. It has an ambiguous column project_id on your second left join, Just replace it with pt.project_id or trd.project_id and it will give desired result.
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when dc.demographic_name = ''',
demographic_name,
''' then trd.demographic_value end) AS ',
replace(demographic_name, ' ', '')
)
) INTO #sql
from demographic_categories;
SET #sql = CONCAT('SELECT pt.test_id, pt.group_id,
', #sql,'
from test_demographic_requirements trd
LEFT JOIN demographic_categories dc ON trd.demographic_id = dc.demographic_id
LEFT JOIN project_tests pt ON pt.test_id = trd.test_id and pt.project_id =1
group by pt.test_id;');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I ran it on a rextester. Here is the link : dynamic_pivot_test

How to match column names and values from joining and related tables?

I have the following DB structure:
cars:
id
make
features:
id
name
cars_feature:
id
car_id
feature_id
value
I want to be able to select all cars with all features and return results with feature.name as the column name and cars_feature.value as the value. Right now I am able to get all feature and all values but I only figured out how to do that with group_concat.
What I am looking for is the following output:
car_id car_make color wheels doors
1 Ford blue alloy
2 Audi alloy 3
Data example: SQLFiddle
The following is a modified version of code that I found at Combine multiple rows into one row MySQL.
SET #sql = NULL;
SELECT GROUP_CONCAT(DISTINCT CONCAT(
'MAX(CASE WHEN `name` = ''',
`name`,
''' THEN value END) AS `',
`name`, '`'
)
) INTO #sql
FROM (SELECT name,
value
FROM features, car_feature
WHERE features.id = car_feature.feature_id) AS car_features_feature;
SET #sql = CONCAT('SELECT car_feature.car_id AS car_id,
cars.make AS car_make,
',
#sql,
'
FROM car_feature
LEFT JOIN cars ON car_feature.car_id = cars.id
LEFT JOIN features ON car_feature.feature_id = features.id
GROUP BY car_id;');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Thank you for the learning experience.

MYSQL pivoting rows and limiting by rows of a specific column

Not entirely sure how to word the question so I gave it my best show and am hoping that the explanation will help get the point across. Any questions, please ask.
I have the following setup for my database:
create table spooner_pec
(
id int,
year varchar(20),
policy_number int,
primary_name varchar(200),
experience_rate decimal(10,2),
mco_name varchar(200)
);
with these values being inserted:
insert into spooner_pec values
(1,'2009',183586,'ZBIN LANDSCAPING INC', 1.22, 'GENEX CARE FOR OHIO'),
(1,'2011',183586,'ZBIN LANDSCAPING INC', 0.93, 'COMPMANAGEMENT HEALTH SYSTEMS, INC.'),
(1,'2012',183586,'ZBIN LANDSCAPING INC', 0.92, 'HEALTH MANAGEMENT SOLUTIONS, INC.'),
(1,'2013',183586,'ZBIN LANDSCAPING INC', 0.50, 'CAREWORKS'),
(1,'2014',183586,'ZBIN LANDSCAPING INC', 0.47, 'UNIVERSITY HOSPITALS COMPCARE'),
(1,'2010',183586,'ZBIN LANDSCAPING INC', 1.27, 'SHEAKLEY UNICOMP')
The query that I have working so far is this:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when year = ',
year,
' then experience_rate end) AS `',
year, '-Pen`'
) ORDER BY year
) INTO #sql
FROM
spooner_pec;
SET #sql = CONCAT('SELECT policy_number, primary_name, ', #sql, '
FROM spooner_pec
GROUP BY policy_number');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
So I have one row for each company and then a year-pen column for each year. What I need to do now is only get the rows where the penalty of the latest year is greater than 1, for example. So if the last year entered for all the data was 2014, I need where 2014-Pen, in this case, is > 1.
SQLFiddle
Do another query to get the last year, and merge that into the SQL.
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when year = ',
year,
' then experience_rate end) AS `',
year, '-Pen`'
) ORDER BY year
) INTO #sql
FROM
spooner_pec;
SELECT MAX(year) INTO #lastYear FROM spooner_pec;
SET #sql = CONCAT('SELECT policy_number, primary_name, ', #sql, '
FROM spooner_pec
GROUP BY policy_number
HAVING `', #lastYear, '-Pen` > 1');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

put results of execute statement into table in MySQL

At MySQL pivot efficiency
I was wondering how to pivot a table of stock prices in MySQL. The consensus seems to be that this is not a good thing to do. I originally wanted each column to be an ID number and each row to be a date. I got much more speed by making each column a date and each row an ID number:
SET ##group_concat_max_len = 1000000;
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(ddate = ',
'ddate',
',closing_price, NULL)) AS ''',
DATE_FORMAT(ddate,'%Y%m%d'),''''
)
) INTO #sql
FROM rawdatatable;
SET #sql = CONCAT('SELECT idnum , ', #sql, ' FROM rawdatatable GROUP BY idnum');
SELECT #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
Is there any way to put the results of the EXECUTE statement into a table, where each column name is a different ddate?
Change this line
SET #sql = CONCAT('SELECT idnum , ', #sql, ' FROM rawdatatable GROUP BY idnum');
to
SET #sql = CONCAT('CREATE TABLE blah AS SELECT idnum , ', #sql, ' FROM rawdatatable GROUP BY idnum');
Try to put the result into a temp table like #Desolator say. Something like this in MySQL console
mysql>CREATE TABLE temp_result AS
SELECT * FROM rawdatatable
WHERE ...;

query pivot with two word with space in column

my query :
set #sql = NULL;
select
group_concat(distinct
concat(
'max(if(first.study = ''',
study, ''', first.avg_scores, NULL)) as ',
study
)
) into #sql
from `table`;
SET #sql = concat('select first.name,
', #sql, '
from `table` first
join `table` second
on first.name = second.name
group by first.name');
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
when data in column "study"
=================================
name | study | avg_scores
=================================
alfa c 75
beta c 70
alfa php 85
beta php 90
and result : its true.
===========================
name | c | php
===========================
alfa 75 85
beta 70 90
the problem when i have data in table like this :
===================================
name | study | avg_scores
===================================
alfa junior c 75
beta junior c 70
alfa junior php 85
beta junior php 90
error :
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'c,max(if(first.study = 'junior php',
first.avg_scores, NULL)) as junior php ' at line 2: prepare stmt from #sql"
so : how to fix my query ?
The problem is that you need to escape the identifiers, because a column name cannot have a space. The following uses double quotes for the name (you can also use backticks):
set #sql = NULL;
select group_concat(distinct concat('max(if(first.study = ''', study,
''', first.avg_scores, NULL)) as "', study, '"'
---------------------------------------------------------------------^ ----------^
)
) into #sql
from `table`;
SET #sql = concat('select first.name, ', #sql, '
from `table` first join `table` second on first.name = second.name
group by first.name');