MySQL Dynamic Pivot Table not giving proper results - mysql

I'm somewhat of a SQL rookie but I'm trying to write a pivot between three tables. I have the below query and it works perfectly aside from the MAX call. It causes my values that are less than the default value to be overridden. I have screenshots of my tables below. Any ideas on how to fix this?
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(cc.company_config_key_id = ', cck.id, ', cc.config_value, \'', cck.default, '\')) AS ', cck.company_config_key
)
) INTO #sql
FROM company_config cc
LEFT JOIN company_config_key cck
ON cck.id = cc.company_config_key_id;
SET #sql = CONCAT('SELECT co.id, co.name, ', #sql, ' FROM companies co LEFT JOIN company_config cc ON cc.company_id = co.id GROUP BY co.id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
companies:
company_config_key:
company_config:
Result (the secondary colors for companies 1 and 2 should be set):

It turns out I just had to set the internal if statement to NULL and then wrapped the max statement in an IFNULL.
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT('IFNULL(MAX(IF(cc.company_config_key_id = ', cck.id, ', cc.config_value, NULL)), \'', cck.default, '\') AS ',cck.company_config_key)
) INTO #sql
FROM company_config cc
LEFT JOIN company_config_key cck
ON cck.id = cc.company_config_key_id;
SET #sql = CONCAT('SELECT co.id, co.name, ', #sql, ' FROM companies co LEFT JOIN company_config cc ON cc.company_id = co.id GROUP BY co.id');
SELECT #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;

Related

Mysql 3 single quotes in a row

I came across the query below to dynamically convert rows into columns with Mysql. Does anyone know what the the 3 single quotes do before & after the Product_Name field?
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'count(case when Product_Name = ''',
Product_Name,
''' then 1 end) AS ',
replace(Product_Name, ' ', '')
)
) INTO #sql
from products;
SET #sql = CONCAT('SELECT pt.partner_name, ', #sql, ' from partners pt
left join sales s
on pt.part_id = s.partner_id
left join products pd
on s.product_id = pd.prod_id
group by pt.partner_name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
https://dev.mysql.com/doc/refman/5.7/en/string-literals.html says:
A ' inside a string quoted with ' may be written as ''.
There are lots of examples on that manual page.

MYSQL dynamic table name select with join and criteria

If I have this schema
lists (lead_id, list_id, campaign_id, ...)
campaign (campaign_id, ...)
custom_list_id (lead_id, ...)
there are many tables with name custom_list_id for various list_id s and I want to:
SELECT * from lists ls inner join campaign c ON c.id=ls.campaign_id
inner join custom_"#LISTID" cll ON ls.lead_id = cll.lead_id
How do I write this query?
thnx
Not sure what sql you really want, but try this:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'INNER JOIN custom_', list_id, 'cll', list_id, ' ON ls.lead_id = cll', list_id '.lead_id')
)
SEPARATOR ' '
) INTO #sql
FROM lists ;
SET #sql = CONCAT('SELECT * from lists ls inner join campaign c ON c.id=ls.campaign_id ', #sql);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Combine multiple rows into a one using sql

In a sql database, I have this:
And I want to create another table that shows the data like this:
Which query should I use?
Possible duplicate of: MySQL pivot table query with dynamic columns. However, what you want is a "pivot" query. You can do this dynamically so you can continue to add new field names and don't have to worry about it pulling those in. Here is the sample code in that question, which would be very similar to what you're trying to do:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(pa.fieldname = ''',
fieldname,
''', pa.fieldvalue, NULL)) AS ',
fieldname
)
) INTO #sql
FROM product_additional;
SET #sql = CONCAT('SELECT p.id
, p.name
, p.description, ', #sql, '
FROM product p
LEFT JOIN product_additional AS pa
ON p.id = pa.id
GROUP BY p.id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
And here's a great tutorial on doing this: http://buysql.com/mysql/14-how-to-automate-pivot-tables.html

MySQL Multiple Query > storing rows into columns

I need to create a SQL query that lists the following tables. Lines from the language list as column names. Thanks
Picture table and query:
If languages are known upfront
SELECT r.id, r.parent,
MAX(CASE WHEN n.language_id = 1 THEN n.name END) cs,
MAX(CASE WHEN n.language_id = 2 THEN n.name END) en
FROM cat_route r LEFT JOIN cat_route_name n
ON r.id = n.cat_route_id
GROUP BY r.id
Here is SQLFiddle demo
If you want it to be dynamic depending on what languages you defined in language
SET #sql = NULL;
SELECT GROUP_CONCAT(CONCAT(
'MAX(CASE WHEN n.language_id = ', id, ' THEN n.name END) `', short, '`'))
INTO #sql
FROM language;
SET #sql = CONCAT(
'SELECT r.id, r.parent, ', #sql, '
FROM cat_route r LEFT JOIN cat_route_name n
ON r.id = n.cat_route_id
GROUP BY r.id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Here is SQLFiddle demo

Joining with dynamic sql

I have the following dynamic sql query which works as intended. But now I want to join the result with the result of another query on account_id. I tried the usual way by making the query a derived table then joining but this doesn't work (I assume it has to do with all the semi-colons). Is there a special way to join a dynamic sql query with another query ?
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(CASE WHEN phone_name = ''',
phone_name,
''' THEN 1 else 0 END) AS `',
phone_name, '`'
)
) INTO #sql
FROM yt;
SET #sql
= CONCAT('SELECT account_id, ', #sql, '
from yt
group by account_id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Can you simply put the rest of your query in your concatenation?
...
/* Your existing code */
SET #sql
= CONCAT('SELECT account_id, ', #sql, '
from yt
group by account_id');
/* Now put your derived table stuff in */
SET #sql
= CONCAT('select a.account_id, b.something_else
from some_table as b join (', #sql, ') as a
on a.account_id = b.account_id');
/* Continue your existing code */
PREPARE stmt FROM #sql;
...