This question already has answers here:
MySQL - Rows to Columns
(13 answers)
MySQL pivot table query with dynamic columns
(3 answers)
Closed 4 years ago.
I have a table like this:
id key year month value
---------------------------------------
1 AD 2000 1 5465
2 AD 2000 2 6445
3 JK 2000 1 7777
4 JK 2000 2 9999
I need to retrive the values like this:
key 2000-1 2000-2
------------------------
AD 5465 6445
JK 7777 9999
I'm having issues with creating the headers, concatenating year and month and displaying the value under the header.
I have another pivot procedure like this:
SELECT
GROUP_CONCAT(
DISTINCT CONCAT(
'MAX(IF(combustible_id = ''',
combustible_id,
''', valor_combustible, NULL)) AS ',
CONCAT("`",admin_combustibles.nombre,"`")
)
) INTO #SQL
FROM
admin_indice_combustibles
INNER JOIN admin_combustibles
ON admin_indice_combustibles.combustible_id = admin_combustibles.id_combustible
WHERE admin_indice_combustibles.estado = 1;
SET #SQL = CONCAT(
'SELECT anio, mes, ',
#SQL,
' FROM admin_indice_combustibles
WHERE estado = 1
GROUP BY anio, mes
ORDER BY id_indice_combustible'
);
PREPARE stmt
FROM
#SQL;
it is working, but it uses more data (because it has a JOIN with another table), now is easier, all the data is in just 1 table, but I can't get it. any hint please?
EDIT:
I'm trying with this code:
BEGIN
SELECT
GROUP_CONCAT(
DISTINCT CONCAT(
' MAX(IF(anio = ''',
DIST.anio,
''' AND mes = ''', DIST.mes, ''', energia_adjudicada_mwh, NULL)) AS ',
CONCAT("`",DIST.anio,"-`", DIST.mes,"`")
)
) INTO #SQL
FROM
admin_contratos_energia_adjudicadas_distribucion_mensual AS DIST
WHERE DIST.activo = 1;
SET #SQL = CONCAT(
'SELECT DIST.key, DIST.contrato_id ',
#SQL,
' FROM admin_contratos_energia_adjudicadas_distribucion_mensual AS DIST
WHERE activo = 1
GROUP BY DIST.key
ORDER BY DIST.contrato_id ');
PREPARE stmt
FROM
#SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
I'm getting the error:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'MAX(IF(anio = '2016' AND mes = '1', energia_adjudicada_mwh, NULL)) AS 2016-1`,' at line 1
I just need to concatenate the year (anio) and month (mes) in the header, and give the value (energia_adjudicada_mwh) to them, for each year and mont, group by key...
This is the table that I have and the table that I need:
Use conditional aggregation like this:
SQL DEMO
SELECT `key`,
MAX( CASE WHEN `year` = 2000 and `month` = 1 THEN `value` END) as `2000-01`,
MAX( CASE WHEN `year` = 2000 and `month` = 2 THEN `value` END) as `2000-02`
FROM t49613951
GROUP BY `key`;
OUTPUT:
Related
This question already has answers here:
How can I return pivot table output in MySQL?
(10 answers)
MySQL pivot table query with dynamic columns
(3 answers)
Closed 3 years ago.
The question is simple. How do i combine the following 2 sql queries into one.
I am using MYSQL v8.0.16 on the MYSQL Workbase UI.
SELECT Node_Type, COUNT(*) AS `count`
FROM node_table_vis
WHERE Node_SpinePlanID = "1"
GROUP BY Node_Type;
RETURNS
TYPE - COUNT
-----------
AGN 18
TJ 26
DSLAM 15
PON 18
CCJ 17
and
SELECT DISTINCT Node_SpinePlanID
FROM node_table_vis
WHERE Node_Exchange = "Exchange 1";
Thats returns
SpinePlanID
------------
1
5
10
So essentially what i want is query that looks like this?
SELECT Node_Type, COUNT(*) AS `count`
FROM node_table_vis
WHERE Node_SpinePlanID =
(
SELECT DISTINCT Node_SpinePlanID
FROM node_table_vis
WHERE Node_Exchange = "Exchange 1";
)
GROUP BY Node_Type;
So I get table that looks like
TYPE - 1 - 5 - 10
-----------------------
AGN 18 x y
TJ 26 x y
DSLAM 15 x y
PON 18 x y
CCJ 17 x y
So this is just throwing errors and not producing the goods. I was able to find the answer the top query, i was able to make the bottom, however i am unable to find an answer to combine both.
Any advice would be really appreciated.
UPDATE/EDIT
I have the following ...
SET ##group_concat_max_len = 10000;
SET #sql = null;
SELECT group_concat(distinct
concat(
'SUM(Node_SpinePlanID = ''',
Node_SpinePlanID,
''',) AS ',
Node_SpinePlanID
)
) INTO #sql
FROM node_table_vis;
SET #sql = CONCAT('SELECT Node_Type, ', #sql, ' FROM node_table_vis GROUP BY Node_Type');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
However the PREPARE stmt is not working? Getting error Code 1064 You have an SQL Error Syntax?
Any Advice on this one?
Are you looking for conditional aggregation?
SELECT Node_Type,
SUM(Node_SpinePlanID = 1) AS count_1,
SUM(Node_SpinePlanID = 5) AS count_5,
SUM(Node_SpinePlanID = 10) AS count_10
FROM node_table_vis
GROUP BY Node_Type;
You can also put the values into rows:
SELECT Node_Type, Node_SpinePlanID, COUNT(*) as cnt
FROM node_table_vis
GROUP BY Node_Type, Node_SpinePlanID;
Without dynamic SQL, probably the best you can do is to put the values in a single row is to put them in a string with two levels of aggregation:
SELECT Node_Type, GROUP_CONCAT(Node_SpinePlanID, ':', cnt SEPARATOR ',')
FROM (SELECT Node_Type, Node_SpinePlanID, COUNT(*) as cnt
FROM node_table_vis
GROUP BY Node_Type, Node_SpinePlanID
) ts
GROUP BY Node_Type;
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
I need help with below scenario. How can we get distinct values in rows as column Names dynamically?
I have data in below format..
Sno firstName Subject Marks
1 ABC Eng 10
2 PQR Hindi 20
3 LM Telgu 20
4 LM Hindi 20
5 LM Eng 39
I need output in below format.
Sno FirstName Eng Hindi Telgu
1 ABC 10 Null Null
2 PQR Null 20 Null
3 LM 39 20 20
If one more subject is added, query should be written dynamic enough to include those values too..
How can Write Query for This?
Hi there as Abecee told you in comment solution for your problem is pivoting table.
Here is query for your table
SELECT Sno, firstName,
SUM(CASE WHEN Subject = 'Eng' THEN Marks ELSE NULL END) AS Eng,
SUM(CASE WHEN Subject = 'Hindi' THEN Marks ELSE NULL END) AS Hindy,
SUM(CASE WHEN Subject = 'Telgu' THEN Marks ELSE NULL END) AS Telgu
FROM t1
GROUP BY firstName
ORDER BY Sno
And here is SQL Fiddle to see how it's work...
GL!
Edit:
Ok based on this bluefeet answer here is dynamics solution for your problem
SET #sql = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT('SUM(CASE WHEN Subject = ''',
Subject,
''' THEN Marks ELSE NULL END) AS ',
REPLACE(Subject, ' ', ''))) INTO #sql
FROM t1;
SET #sql = CONCAT('SELECT Sno, firstName, ', #sql, '
FROM t1
GROUP BY firstName
ORDER BY Sno');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
First part of this
SET #sql = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT('SUM(CASE WHEN Subject = ''',
Subject,
''' THEN Marks ELSE NULL END) AS ',
REPLACE(Subject, ' ', ''))) INTO #sql
FROM t1;
is to dynamically create this part of first query I wrote
SUM(CASE WHEN Subject = 'Eng' THEN Marks ELSE NULL END) AS Eng,
SUM(CASE WHEN Subject = 'Hindi' THEN Marks ELSE NULL END) AS Hindy,
SUM(CASE WHEN Subject = 'Telgu' THEN Marks ELSE NULL END) AS Telgu
the second part is to create prepared statement and to include dynamically created part into this
SELECT Sno, firstName,
-- here you add dynamically created part #sql
FROM t1
GROUP BY firstName
ORDER BY Sno
you do that with CONCAT in this part of code
SET #sql = CONCAT('SELECT Sno, firstName, ', #sql, '
FROM t1
GROUP BY firstName
ORDER BY Sno');
when you create that from that string you prepare statement and execute it
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Hope that is a little bit clear now...
Here is SQL Fiddle so you can see that you can compare both query and see how it's work..
GL!
P.S. if you have any question fill free to ask in comment bellow
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');
I have below database table : Table name - dim_module
id Creation_Date Goals Alternative Value
-----------------------------------------------------------
1 2014-04-17 10:09:30 G1 A 0.86
2 2014-04-17 10:09:30 G1 B 0.87
3 2014-04-17 10:09:30 G2 A 0.5
4 2014-04-17 10:09:30 G2 B 0
I am using below procedure for getting desired output
CREATE DEFINER=`root`#`localhost` PROCEDURE `stmt`()
BEGIN
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(goals = ''',
goals,
''', round(value, 2), NULL)) AS ',
goals
)
) INTO #sql
FROM sgwebdb.dim_module;
SET #sql = CONCAT('SELECT alternative, ', #sql, ' FROM sgwebdb.dim_module GROUP BY alternative');
prepare stmt from #sql;
But if Dim_Module don't have any row then procedure is not take care and I am getting error.
Error Code: 1064. 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 'NULL' at line 1
Please help to take care of empty table.
Maybe because #sql is null.
Try setting it to some value with IFNULL
SET #sql = CONCAT('SELECT alternative, ', IFNULL(#sql,'somecolumnor*here'), ' FROM sgwebdb.dim_module GROUP BY alternative');
Or detect that #sql is null and do something else.
You may check #sql before using it within your second SELECT:
IF #sql
THEN
SET #sql = CONCAT('SELECT alternative, ', #sql, ' FROM sgwebdb.dim_module GROUP BY alternative');
prepare stmt from #sql;
END IF;