I am trying to make a cross tab pivot table. I need to get all teams from the database table dynamically on separate columns instead of specifying names of the teams in the query which I am currently doing. I have looked at another example i.e. MySQL pivot table query with dynamic columns.
At the moment I am receiving the results fine from the database but only by manually typing what column I need in the query. See the example below:
SELECT IFNULL(DATE( date_posted ), 'Total') AS DATE,
SUM(CASE WHEN added_by LIKE '%Team One%' THEN 1 ELSE 0 END) AS Team1,
SUM(CASE WHEN added_by LIKE '%Team Two%' THEN 1 ELSE 0 END ) AS Team2,
COUNT( added_by ) AS Daily_Total FROM teamdata WHERE status LIKE
'%completed%' GROUP BY IFNULL(DATE( date_posted ), 'Total') DESC WITH ROLLUP;
Which displays 4 columns of DATE, Team1, Team2 and Daily_Total. But at a later stage there will be more columns to add in but to be done dynamically. I am trying to execute this prepared statement but to no success:
SET #sql = NULL;
SELECT GROUP_CONCAT( DISTINCT
CONCAT(
'sum(CASE WHEN added_by = ''',
added_by,
''' THEN 1 else ''-'' END) AS `', added_by,
'`'
)
) into #sql
FROM teamdata;
SET #sql
= CONCAT('SELECT IFNULL(DATE( date_posted ), \'Total\') AS DATE, ', #sql, '
from teamdata
WHERE status = \'completed\'
GROUP BY IFNULL(DATE( date_posted ), \'Total\') DESC WITH ROLLUP');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Please could I get further help on this.
Related
I have a query to report some data :
select r.m_id,
count(distinct case when r.sal = '1val' then r.login end) as 1val,
count(distinct case when r.sal = '2val' then r.login end) as 2val,
count(distinct case when r.sal = '3val' then r.login end) as 3val,
...
from read_log r
inner join mes m on m.id = r.m_id
where
YEAR(m.send_date) = YEAR(curdate())
group by r.m_id
r.sal value in count(distinct case when r.sal = '1val' then r.login end) as 1val only changes. Finally it shows results in each column for every r.sal. There are currently over 80 diffrent r.sal and its growing.
My question is:
It is possible to take value for r.sal from another table?
Like new table sal with this 1val, 2val, 3val, 4val, 5val etc...?
Maybe loop or something like that:
count(distinct case when r.sal = (select val from sal) then r.login end)
(I know its wrong but maybe it will illustrate it better)
count(distinct case... is great to show data for each r.sal value in the other column but maybe is another way to achieve that...
CREATE TABLE sal_table (sal CHAR(4));
INSERT INTO sal_table VALUES ('1val'), ('2val'), ... ;
CREATE PROCEDURE get_data ()
BEGIN
SELECT CONCAT (
'select r.m_id, ',
GROUP_CONCAT(
CONCAT(
'count(distinct case when r.sal = ''',
sal,
''' then r.login end) as `',
sal,
'`'
)
),
' from read_log r ',
'inner join mes m on m.id = r.m_id ',
'where YEAR(m.send_date) = YEAR(curdate()) ',
'group by r.m_id'
)
INTO #sql
FROM sal_table;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=af55c52aca3280410fba1f3a453aab09
PS. Recommended edition: WHERE m.send_date >= DATE_FORMAT(CURRENT_DATE, '%Y-01-01') AND m.send_date < DATE_FORMAT(CURRENT_DATE + INTERVAL 1 YEAR, '%Y-01-01'). Such condition is sargable rather than your one.
I am trying to write up something that can be run once and exported with all the data from a prepared statement and a select statement. Is it possible to union them?
example dynamic pivot table
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'format(sum(case when field_key = ''',
field_key,
''' then field_value end), 0) ',
field_key
)
) INTO #sql
FROM
Meeting;
SET #sql = CONCAT('SELECT Meeting_id, ', #sql, '
FROM Meeting
GROUP BY Meeting_id'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
example select statement
set #startdate = '2020-11-10'
set #enddate = '2020-12-30'
select column1,
column2,
column3,
if(col.id = id,1,0) column4,
if(col.id = id,0,1) column5
from Meeting
group by col.id
order by column2;
If its not possible to UNION ALL them then what would be your suggestions?
Unions have to have the same number of columns (and their names are taken from the first query in the union), and here the pivot query has a dynamic number. You would need to adjust the columns of your second select to match and add it to your #sql as a union.
Often with unions you add a type field that is hardcoded and different for each of the unioned queries, and have each query return null for columns that aren't relevant to that query.
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.
If I have these data in MySQL database:
PID LANG TRANS
1 EN Apple
1 DE Apfle
I want to get results in sql:
PID EN_TRANSLATION DE_TRANSLATION
1 Apple Apfle
How to do this? I already have tables and everything but need help writing query that will give me columns per language per result for each product.
NOTE: I don't know set of language(s) ! It can be EN, DE or whatever else..
Thx!
If you have known set of LANG then you can use the following technique to generate the pivot view
select
PID,
max(case when LANG = 'EN' then TRANS end) as EN_TRANSLATION,
max(case when LANG = 'DE' then TRANS end) as DE_TRANSLATION
from table_bame
group by PID
If the LANG values are unknown then you need to use dynamic sql for this as
set #sql = null;
select
group_concat(distinct
concat(
'max(case when LANG = ''',
LANG,
''' then TRANS end) AS ',
concat(LANG,'_TRANSLATION')
)
) into #sql
from table_name ;
set #sql = concat('select PID, ', #sql, ' from table_name
group by PID
');
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
http://www.sqlfiddle.com/#!9/95d29/1
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