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.
Related
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;
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
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
This is a Question related to my original question
Pivot Table Using MySQL
Data in the tables are saved like this now
I have two tables Triples and Tags
Triples Table has the following Columns
id PostID TagID Value
1 1 1 Murder
2 1 1 Theft
3 2 2 Knife
4 2 2 Gun
Tags Table has the following Columns
id TagName
1 Incident
2 Weapon
I am trying to write sql to create a Pivot Table with Dynamic Headers
Output should be like this
PostID Incident Weapon
1 Murder,Theft
2 Knifie,Gun
I written a inefficient and partial sql query for this, Any help in writing this sql appreciated
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(CASE WHEN TagName = ''',
TagName,
''' THEN p.value END) AS `',
TagName, '`'
)
) INTO #sql
FROM tags;
SET #sql
= CONCAT('CREATE VIEW PostTags as SELECT p.postid, p.id, ', #sql, '
from triples p
left join tags t
on p.tagid = t.id
group by p.postid, p.id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
You will have to build two strings, one for the inner rotation to create the columns of Incident and Weapon, and the second string with use GROUP_CONCAT for the outer query:
SET #sql = NULL;
SET #sql2 = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'group_concat(',
TagName,
' separator '', '') as `',
TagName, '`'
)
)
INTO #sql2
FROM tags;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(CASE WHEN TagName = ''',
TagName,
''' THEN p.value END) AS `',
TagName, '`'
)
)
INTO #sql
FROM tags;
SET #sql = CONCAT('select postid, ', #sql2, '
from
(
SELECT p.postid, p.id, ', #sql, '
from triples p
left join tags t
on p.tagid = t.id
group by p.postid, p.id
) d
group by postid');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
See SQL Fiddle with Demo
This is creating the SQL code:
select postId,
group_concat(incident separator ', ') incident,
group_concat(Weapon separator ', ') Weapon
from
(
SELECT p.postid, p.id,
max(CASE WHEN TagName = 'Incident' THEN p.value END) AS `Incident`,
max(CASE WHEN TagName = 'Weapon' THEN p.value END) AS `Weapon`
from triples p
left join tags t
on p.tagid = t.id
group by p.postid, p.id
) d
group by postId;
See SQL Fiddle with Demo
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;
...