i have the following tables:
**entries**
entry_id | date | engineer | project
**entries_allowanes_map**
entry_id | allowance_id
**allowances**
allowance_id | allowance_name
I want to create a SELECT query that will give the following result:
entry_id | date | engineer | project | allowance_name1 | allowance_name2 | allowance_name_n...
The queries I have tried return a row for each allowance an entry has registered with. I want just one row with all allowances attached to it.
Thanks in advance
I would propose doing this with group_concat(). It doesn't put the values in separate columns, but it does put everything for a given entry on one row:
select e.entry_id, e.date, e.engineer, e.project,
group_concat(a.allowance_name) as allowances
from entries e join
entries_allowances_map f
on e.entry_id = eam.entry_id
allowances a
on eam.allowance_id = a.allowance_id
group by e.entry_id;
Here is the query that I got:
It outputs your expected results in different columns:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'(SELECT max(CASE WHEN AL.ALLOWANCE_ID = ''',
ALLOWANCE_ID,
''' THEN 1 END) AS `',
ALLOWANCE_ID, '` FROM entries_allowanes_map AL WHERE E.ENTRY_ID = AL.ENTRY_ID ) AS `',
ALLOWANCE_NAME, '`'
)
) INTO #sql
FROM allowances;
SET #sql
= CONCAT('SELECT E.ENTRY_ID, E.DATE, E.ENGINEER, E.PROJECT, ', #sql, '
FROM entries as e');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Here is the SqlFiddle
Try
SELECT * FROM entries as e
INNER JOIN entries_allowanes_map as a ON e.entry_id=e.entry_id
INNER JOIN allownces as al ON al.allownce_id=a.allowance_id
Related
I need to create a view from 2 tables
Table 1
app_id cat_id approver level proj_id
1 1 pm_id 1 731
1 2 dm_id 2 843
1 3 dm_id 1 859
2 4 bo_id 1 859
table 2
proj_id pm_id dm_id bo_id
731 100102 100034 100121
843 123121 145721 104321
859 112312 132434 132435
My approver id is in table 2 and the table 1 denotes who is the approver for the project based on the level. I want to create a view for the list of approval pending with the pm, dm and bo.
e.g. result table
app_id cat_id approver
1 1 100102
1 2 145721
1 3 132434
2 4 132435
Use left join to join two tables together, then use case when to get approver.
select
table1.app_id,
table1.cat_id,
case when table1.approver = 'pm_id' then table2.pm_id
when table1.approver = 'dm_id' then table2.dm_id
when table1.approver = 'bo_id' then table2.bo_id
end as approver
from table1
left join table2 on table1.proj_id = table2.proj_id
See demo in rextester.
Edit:
If you have dynamic approver, try this:
SET #sql = NULL;
SELECT
CONCAT('CASE', GROUP_CONCAT(DISTINCT
CONCAT(' WHEN table1.approver = ''',
approver,
''' THEN table2.', approver) SEPARATOR ' '), ' END AS approver'
) INTO #sql
FROM table1;
SET #sql = CONCAT('SELECT table1.app_id, table1.cat_id, ', #sql, ' FROM table1 LEFT JOIN table2 ON table1.proj_id = table2.proj_id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Also have a demo in Rextester.
Create VIEW:
create view view1
as
select
table1.app_id,
table1.cat_id,
case when table1.approver = 'pm_id' then table2.pm_id
when table1.approver = 'dm_id' then table2.dm_id
when table1.approver = 'bo_id' then table2.bo_id
end as approver
from table1
left join table2 on table1.proj_id = table2.proj_id
Probably a very basic error but here is my problem.
There are users who are giving likes to certain pages of a given document and my aim is to return a breakdown of pages liked per user
Here are (a simplified view of) the two following tables:
User table
id name
---------
1 Jim
2 John
Vote table
userid pageno voteup
1 1 1
1 2 1
2 1 1
2 2 1
2 3 1
My desired output would be the following:
id name Page 1 Page 2 Page 3
1 Jim 1 1 0
2 John 1 1 1
I've made my prepared statement as followed. My aim is to display 'Page 1', 'Page 2' and so on for the column names instead of the 'test' below but as my pageno field is an int i fail in formatting the column name. I have tried various things but with no luck.
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(v.pageno = ',
pageno,
', v.voteup, 0)) AS ',
'test'
)
) INTO #sql
FROM vote;
SET #sql = CONCAT('SELECT u.id, u.name, ', #sql, '
FROM user u
LEFT JOIN vote AS v
ON u.id = v.id
GROUP BY u.id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I'm sure this is something very basic I am missing. Could you help?
Thanks in advance
Link to SQLFiddle
This will do the trick although is not dynamic, if you need a dynamic solution.....
select
n.id,
n.name,
CASE WHEN v.pageno=1 THEN sum(v.voteup) ELSE NULL END as "Page 1"
CASE WHEN v.pageno=2 THEN sum(v.voteup) ELSE NULL END as "Page 2"
from votetable as v
join usertable as n on n.id = v.userid
I have 2 tables:
table1:
|id|create_date|title |type |
-------------------------------
| 1|2015-07-20 |bla-bla|TICKET|
table2_meta:
|id|table1_id|meta_name|meta_value|
-----------------------------------
| 1| 1 | status | new |
| 2| 1 | priority| low |
| 3| 1 | owner | alex |
Now, i wish to select it like this:
|id|create_date|title |status|priority|owner|
|1 |2015-07-20 |bla-bla|new |low |alex |
My solution is:
SELECT
t1.id,
t1.event_date,
case when m.meta_name="status" then m.meta_value end as status,
case when m.meta_name="priority" then m.meta_value end as priority,
case when m.meta_name="owner" then m.meta_value end as owner
FROM table1 as t1
LEFT JOIN table2_meta as m
on m.table1_id=t1.id
WHERE t1.type='TICKET'
GROUP BY t1.id
So, it works. But seems a litle bit ugly.
My question is:
Are there any other solutions to this select and how to make it more productive?
Hey try this in your case for pivoting of table SQLFIDDLE
set #sql = null;
select
group_concat(distinct
concat(
'max(case when meta_name = ''',
meta_name,
''' then value end) AS ',
concat(meta_name)
)
) into #sql
FROM table1 as t1
LEFT JOIN table2 as m
on m.table1_id=t1.id
WHERE t1.type='TICKET';
set #sql = concat('select t1.id,', #sql, ' FROM table1 as t1
LEFT JOIN table2 as m
on m.table1_id=t1.id
WHERE t1.type=''TICKET''
GROUP BY t1.id
');
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
In oracle you could:
Instead of case when you could use pivot.
SELECT * FROM table2
PIVOT (
meta_value FOR (meta_name) IN ('Status' AS status, 'Priority' AS priority, 'owner' AS Ownser))
SOLVED
I'am so sorry guys, it was so easy, but workday smashed my brain.
I just had to made the sum on the basis of id to get what i need, like
this:
SET #sql = CONCAT('SELECT tt.Id, SUM(tt.Values) AS TOTAL, ' #sql, ' FROM db.Table tt GROUP BY tt.Id');
Thank you for help!
Your help is really appreciated :)
I have a generated table of the following a look:
id | key1 | key2 | ... | keyN
id_val1 | k1_val1 | k2_val1 | ... | kN_val1
... | ... | ... | ... | ...
id_valM | k1_valM | k2_valM | ... | kN_valM
it is generated with the code:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(tt.Keys = ''',
tt.Keys,
''', tt.Values, NULL)) AS ',
tt.Keys
)
) INTO #sql
FROM db.Table tt;
SET #sql = CONCAT('SELECT tt.Id, ', #sql, ' FROM db.Table tt GROUP BY tt.Id WITH ROLLUP');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
What I have to do is to add Total column, like this:
id | key1 | key2 | ... | keyN | Total
id_val1 | k1_val1 | k2_val1 | ... | kN_val1 | sum(k1_val1, k2_val1,...,kN_val1)
... | ... | ... | ... | ... | ...
id_valM | k1_valM | k2_valM | ... | kN_valM | sum(k1_valM, k2_valM,...,kN_valM)
"WITH ROLLUP" didn't work though, it only added another row with max values in columns, while I need sums in rows.
The problem is the fact that number of columns and their names may differ through time. And using their names properly is the problem itself :).
For example i got the names of columns, but how to use them, as they don't belong to any table? I can convert dynamically built sql to the following look. But can you tell me how the #xxx should look:
SET #sql = CONCAT('SELECT tt.Id, SUM(', #xxx,') AS TOTAL, ' #sql, ' FROM db.Table tt GROUP BY tt.Id WITH ROLLUP');
Thanks in advance,
Michael.
If I am interpreting this correctly, I think this is what you want to do. You aren't actually doing a sum, correct? You are adding all of the field values for each row. The second GROUP_CONCAT here should create the list of fields with plus signs (+) in between them. Give it a shot.
SET #sql = NULL;
SET #sql2 = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(tt.Keys = ''',
tt.Keys,
''', tt.Values, NULL)) AS ',
tt.Keys
)
) INTO #sql,
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(tt.Keys = ''',
tt.Keys,
''', tt.Values, NULL))'
)
SEPARATOR '+'
) INTO #sql2
FROM db.Table tt;
SET #sql = CONCAT('SELECT tt.Id, ', #sql, ', ', #sql2,' AS Total FROM db.Table tt GROUP BY tt.Id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I have two tables Triples and Tags
Triples Table has the following Columns
id PostID TagID Value
1 1 1 Murder
2 1 2 New Brunswick
3 2 1 Theft
4 2 3 Gun
Tags Table has the following Columns
id TagName
1 Incident
2 Location
3 Weapon
I am trying to write sql to create a Pivot Table with Dynamic Headers
Output should be like this
PostID Incident Location Weapon
1 Murder New Brunswick
2 Theft Gun
Any help in writing the SQL would be appreciated. I have seen examples online but could not figure out this one
In order to pivot the data in MySQL, you will need to use both an aggregate function and a CASE expression.
If you have a known number of columns, then you can hard-code the query:
select p.postid,
max(case when t.tagname = 'Incident' then p.value end) Incident,
max(case when t.tagname = 'Location' then p.value end) Location,
max(case when t.tagname = 'Weapon' then p.value end) Weapon
from triples p
left join tags t
on p.tagid = t.id
group by p.postid;
See SQL Fiddle with Demo
But if you have an unknown number of columns, then you will need to use a prepared statement to generate dynamic SQL:
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('SELECT p.postid, ', #sql, '
from triples p
left join tags t
on p.tagid = t.id
group by p.postid');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
See SQL Fiddle with Demo.
Both will give the result:
| POSTID | INCIDENT | LOCATION | WEAPON |
----------------------------------------------
| 1 | Murder | New Brunswick | (null) |
| 2 | Theft | (null) | Gun |