Mysql group by with normal column and mysql function aliases column - mysql

I have been trying to group by the mysql group by in normal column and mysql function aliases column where the mysql function aliases wont work group by
The query i tried and which should work according to the mysql documentation.
SELECT `project`.`project_name`, SUM(cost_allocated) AS cost_allocated,
count(task_id) as countTask,
GROUP_CONCAT(task_registration.members SEPARATOR ';') AS members,
GROUP_CONCAT(task_registration.indicators SEPARATOR ';') AS indicators,
GROUP_CONCAT(task_registration.percent_complete SEPARATOR ';') AS percent_complete,
GROUP_CONCAT(task_registration.status SEPARATOR ';') AS status,
DATE_FORMAT(`task_registration`.`created_at`, '%M') AS month
FROM (`project`)
INNER JOIN `task_registration` ON `task_registration`.`project` = `project`.`project_id`
GROUP BY `task_registration`.`project`,`month`
ORDER BY `project`.`project_id` desc
The result i get
Now after removing the normal column group by and just adding mysql function aliases column it works fine but i need both
SELECT `project`.`project_name`, SUM(cost_allocated) AS cost_allocated,
count(task_id) as countTask,
GROUP_CONCAT(task_registration.members SEPARATOR ';') AS members,
GROUP_CONCAT(task_registration.indicators SEPARATOR ';') AS indicators,
GROUP_CONCAT(task_registration.percent_complete SEPARATOR ';') AS percent_complete,
GROUP_CONCAT(task_registration.status SEPARATOR ';') AS status,
DATE_FORMAT(`task_registration`.`created_at`, '%M') AS month
FROM (`project`)
INNER JOIN `task_registration` ON `task_registration`.`project` = `project`.`project_id`
GROUP BY `month`
ORDER BY `project`.`project_id` desc
after removing task_registration`.`project from group by
GROUP BY `task_registration`.`project`,`month` Doesnt work in this case
http://sqlfiddle.com/#!2/18389/2 i have tried this so far

Very difficult to work out what you want without table declarations, sample input data and sample output data, but from your comment all I can suggest is using the 2nd query as a sub query and joining it to the results of the first query:-
SELECT project.project_name,
SUM(cost_allocated) AS cost_allocated,
count(task_id) as countTask,
GROUP_CONCAT(task_registration.members SEPARATOR ';') AS members,
GROUP_CONCAT(task_registration.indicators SEPARATOR ';') AS indicators,
GROUP_CONCAT(task_registration.percent_complete SEPARATOR ';') AS percent_complete,
GROUP_CONCAT(task_registration.status SEPARATOR ';') AS status,
DATE_FORMAT(task_registration.created_at, '%M') AS month,
sub0.cost_allocated AS months_cost_allocated,
sub0.countTask AS months_countTask,
sub0.members AS months_members,
sub0.indicators AS months_indicators,
sub0.percent_complete AS months_percent_complete,
sub0.status AS months_status
FROM (`project`)
INNER JOIN `task_registration` ON `task_registration`.`project` = `project`.`project_id`
INNER JOIN
(
SELECT DATE_FORMAT(task_registration.created_at, '%M') AS month,
SUM(cost_allocated) AS cost_allocated,
COUNT(task_id) as countTask,
GROUP_CONCAT(task_registration.members SEPARATOR ';') AS members,
GROUP_CONCAT(task_registration.indicators SEPARATOR ';') AS indicators,
GROUP_CONCAT(task_registration.percent_complete SEPARATOR ';') AS percent_complete,
GROUP_CONCAT(task_registration.status SEPARATOR ';') AS status
FROM (project)
INNER JOIN task_registration ON task_registration.project = project.project_id
GROUP BY `month`
) sub0
ON DATE_FORMAT(task_registration.created_at, '%M') = sub0.`month`
GROUP BY task_registration.project,
`month`,
months_cost_allocated,
sub0.countTask AS months_countTask,
sub0.members AS months_members,
sub0.indicators AS months_indicators,
sub0.percent_complete AS months_percent_complete,
sub0.status AS months_status
ORDER BY project.project_id desc

Thank you for the answer i did it on my own
SELECT COUNT( i.project_name ) AS completed_projects,i.month
FROM (
SELECT `project`.`project_name` , SUM( cost_allocated ) AS cost_allocated, COUNT( task_id ) AS countTask, GROUP_CONCAT( task_registration.members
SEPARATOR ';' ) AS members, GROUP_CONCAT( task_registration.indicators
SEPARATOR ';' ) AS indicators, GROUP_CONCAT( task_registration.percent_complete
SEPARATOR ';' ) AS percent_complete, GROUP_CONCAT( task_registration.status
SEPARATOR ';' ) AS
STATUS , DATE_FORMAT( task_registration.created_at, '%M' ) AS
MONTH FROM (
`project`
)
INNER JOIN `task_registration` ON `task_registration`.`project` = `project`.`project_id`
GROUP BY `task_registration`.`project`
ORDER BY `project`.`project_id` DESC
) AS i
GROUP BY i.month
http://sqlfiddle.com/#!2/18389/11

Related

MySql Inner join and exclude

I have the following query. I need it to include all records from the 'yahrzeit' and tbldecedent table and the ones that are a match (dupes) should only be listed once.
SELECT *, Count(*)
FROM yahrzeit
WHERE confirmed = 1
INNER JOIN tbldecedent ON CONCAT( yahrzeit.firstName, ' ', yahrzeit.middleName, ' ', yahrzeit.lastName ) = tbldecedent.Name
AND DATE_FORMAT( CONCAT( yahrzeit.gregorianYear, '-', yahrzeit.gregorianMonthNum, '-', yahrzeit.gregorianDay ) , '%Y-%m-%d' ) = tbldecedent.EngDate
GROUP BY tbldecedent.Name, tbldecedent.EngDate
Where clauses belong after the joins.
Since we're using outer joins we have to make sure the where clause criteria for the matching records is moved to the join or the outer join is negated.
in mySQL to simulate a full outer join we simple do a left and right join with a union ALL (union does a distinct which removes the duplicates)
SELECT tbldecedent.Name, tbldecedent.EngDate, Count(*) as Cnt
FROM yahrzeit
LEFT JOIN tbldecedent
ON CONCAT( yahrzeit.firstName, ' ', yahrzeit.middleName, ' ', yahrzeit.lastName ) = tbldecedent.Name
AND DATE_FORMAT( CONCAT( yahrzeit.gregorianYear, '-', yahrzeit.gregorianMonthNum, '-', yahrzeit.gregorianDay ) , '%Y-%m-%d' ) = tbldecedent.EngDate
WHERE yahrzeit.confirmed = 1
AND tblDecedent.name is null -- add this to only show no matches.
GROUP BY tbldecedent.Name, tbldecedent.EngDate
UNION ALL
SELECT tbldecedent.Name, tbldecedent.EngDate, Count(*) as cnt
FROM yahrzeit
RIGHT JOIN tbldecedent
ON CONCAT( yahrzeit.firstName, ' ', yahrzeit.middleName, ' ', yahrzeit.lastName ) = tbldecedent.Name
AND DATE_FORMAT( CONCAT( yahrzeit.gregorianYear, '-', yahrzeit.gregorianMonthNum, '-', yahrzeit.gregorianDay ) , '%Y-%m-%d' ) = tbldecedent.EngDate
AND yhrzeit.confirmed = 1
WHERE CONCAT( yahrzeit.firstName, ' ', yahrzeit.middleName, ' ', yahrzeit.lastName ) is null -- add this to only show no matches.
GROUP BY tbldecedent.Name, tbldecedent.EngDate
To better understand joins I recommend: https://blog.codinghorror.com/a-visual-explanation-of-sql-joins/ the venn diagram approach is a good one.
Lastly, I don't recommend a select *, count() with a group by containing only two fields. Select should only include the values in the group by plus
aggregates or constants. Current version of MySQL wouldn't let you get away with this without changing a global setting, and other engines simply don't support this method. MySQL extends the group by to allow it; but the results can be unexpected for the columns not listed in the group by . More on that in the docs: https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

unknown column in IN/ALL/ANY subquery where clause

Problem:
I know it's documented in MYSQL DOCUMENTS That in where clause "alias" cannot be used since where clause is not populated yet. But i have to get the data matched from other table values in where clause (IN condition).
I have also read some similar kind of post but this one is quite different & big complex one. I couldn't make it working with my efforts of last 3 days.
It's showing error (excepted as per documentation)
UNKNOWN COLUMN "Ind_ID" in WHERE CLAUSE
I have to match similarly for FA_ID & PREFERRED_LOCATION_ID field
Select a.job_id, a.Employer_ID, a.Sub_user_id,
Date_format(a.creation_on,'%d-%m-%Y') as Created_date, a.Job_type,
a.Designation, a.Open_Positions, a.Job_Description, a.Min_age,
a.Max_age, a.min_exp, a.max_exp, a.Hide_Salary, a.company_name,
a.About_Company, a.Contact_person_name, a.Contact_No, a.Refresh_type,
a.Response_type,
(Select GROUP_CONCAT(DISTINCT g.Education ORDER BY pjedu.Education_ID
SEPARATOR ', ') user_education
from e_pj_edu pjedu
INNER JOIN education g ON FIND_IN_SET(g.Edu_ID, pjedu.Education_ID)
where a.job_id = pjedu.Job_ID
) as Education_ID,
(Select GROUP_CONCAT(DISTINCT h.FA_description ORDER BY uf.FA_ID
SEPARATOR ', ') FA
from e_pj_fa uf
INNER JOIN functional_area h ON FIND_IN_SET(h.FA_ID, uf.FA_ID)
where a.Job_ID = uf.Job_ID
) as FA_ID,
(Select GROUP_CONCAT(DISTINCT i.Industry_description ORDER BY
ui.Industry_ID SEPARATOR ', ') Industry_ID
from e_pj_industry ui
INNER JOIN industry i ON FIND_IN_SET(i.Industry_ID, ui.Industry_ID)
where a.Job_ID = ui.Job_ID
) as Ind_ID,
(Select GROUP_CONCAT(DISTINCT j.location_name ORDER BY
upl.Location_ID SEPARATOR ', ') Location_ID
from e_pj_locations upl
INNER JOIN locations j ON FIND_IN_SET(j.location_id, upl.Location_ID)
where a.Job_ID = upl.Job_ID
) as Preferred_Location_ID,
(Select GROUP_CONCAT(DISTINCT uk.Keyword_Name ORDER BY uk.Keyword_ID
SEPARATOR ', ') keyskills
from e_pj_keywords uk
where a.Job_ID = uk.Job_ID
) as Keyword_Name,
GROUP_CONCAT(DISTINCT cc.salary_description ORDER BY cc.salary_ID
SEPARATOR ', ') Min_salary,
GROUP_CONCAT(DISTINCT dd.salary_description ORDER BY dd.salary_ID
SEPARATOR ', ') Max_salary
from post_jobs a
INNER JOIN user_salary cc ON FIND_IN_SET(cc.salary_ID, a.Min_salary)
INNER JOIN user_salary dd ON FIND_IN_SET(dd.salary_ID, a.Max_salary)
WHERE a.Designation LIKE '%MIS%' or a.company_name LIKE '%MIS%'
And a.max_exp <= 9
And a.Max_salary<=110
And Ind_ID IN (10001,10002,10004)
And FA_ID IN(1001)
group by a.job_id
First thing that comes in my mind is just move your aliased where conditions to outer query, i.e.:
select * from (
Select a.job_id ....
WHERE a.Designation LIKE '%MIS%' or a.company_name LIKE '%MIS%'
And a.max_exp <= 9
And a.Max_salary<=110
group by a.job_id
) inner
where
Ind_ID IN (10001,10002,10004)
And FA_ID IN(1001)
GL!
Posting revised query which worked. May be this helps someone from wasting 3 days like me :-)
select * from (
Select a.job_id, a.Employer_ID, a.Sub_user_id, Date_format(a.creation_on,'%d-%m-%Y') as Created_date, a.Job_type, a.Designation, a.
Open_Positions, a.Job_Description, a.Min_age, a.Max_age, a.min_exp, a.max_exp, a.Hide_Salary, a.company_name, a.About_Company, a.Contact_person_name,
a.Contact_No, a.Refresh_type, a.Response_type,
(Select GROUP_CONCAT(DISTINCT g.Education ORDER BY pjedu.Education_ID SEPARATOR ', ') user_education
from e_pj_edu pjedu
INNER JOIN education g ON FIND_IN_SET(g.Edu_ID, pjedu.Education_ID)
where a.job_id = pjedu.Job_ID
) as Education_ID,
(Select GROUP_CONCAT(DISTINCT h.FA_description ORDER BY uf.FA_ID SEPARATOR ', ') FA
from e_pj_fa uf
INNER JOIN functional_area h ON FIND_IN_SET(h.FA_ID, uf.FA_ID)
where a.Job_ID = uf.Job_ID
) as FA_ID,
(Select GROUP_CONCAT(DISTINCT i.Industry_description ORDER BY ui.Industry_ID SEPARATOR ', ') Industry_ID
from e_pj_industry ui
INNER JOIN industry i ON FIND_IN_SET(i.Industry_ID, ui.Industry_ID)
where a.Job_ID = ui.Job_ID
) as Ind_ID,
(Select GROUP_CONCAT(DISTINCT j.location_name ORDER BY upl.Location_ID SEPARATOR ', ') Location_ID
from e_pj_locations upl
INNER JOIN locations j ON FIND_IN_SET(j.location_id, upl.Location_ID)
where a.Job_ID = upl.Job_ID
) as Preferred_Location_ID,
(Select GROUP_CONCAT(DISTINCT uk.Keyword_Name ORDER BY uk.Keyword_ID SEPARATOR ', ') keyskills
from e_pj_keywords uk
where a.Job_ID = uk.Job_ID
) as Keyword_Name,
GROUP_CONCAT(DISTINCT cc.salary_description ORDER BY cc.salary_ID SEPARATOR ', ') Min_salary,
GROUP_CONCAT(DISTINCT dd.salary_description ORDER BY dd.salary_ID SEPARATOR ', ') Max_salary
from post_jobs a
INNER JOIN user_salary cc ON FIND_IN_SET(cc.salary_ID, a.Min_salary)
INNER JOIN user_salary dd ON FIND_IN_SET(dd.salary_ID, a.Max_salary)
group by a.Job_id
) aa
WHERE Designation LIKE '%op%' or company_name LIKE '%op%'
And max_exp <= 15
And Max_salary<=120
and Ind_ID IN (10001,10002,10004,10003)
And FA_ID IN(1001,1002,1003)
group by Job_id

Showing multiple values while joining tables

Hello I am trying following query
I am having four tables post_messages post_message_users, link_details,tags
post_messages has 1:N relation ship with link_details,tags
tables
I am writing following query to fetch related data from all tables.
But problem is that it is showing same value many times.
SELECT
p_m.*,
p_m_u.*,
GROUP_CONCAT( tags.tag SEPARATOR ';')
AS 'MESSAGE_TAGS',
GROUP_CONCAT( linkdtl.link_id SEPARATOR ';')
AS `LINK_ID`,
GROUP_CONCAT( linkdtl.link SEPARATOR ';')
AS 'LINK',
GROUP_CONCAT( linkdtl.link_title SEPARATOR ';')
AS 'LINK_TITLE'
FROM post_message_users AS p_m_u
LEFT JOIN post_messages AS p_m
ON p_m.messageid = p_m_u.messageid
LEFT JOIN tags
ON p_m.messageid=tags.message_id
LEFT JOIN link_details AS linkdtl
ON p_m_u.messageid=linkdtl.message_id
GROUP BY p_m_u.messageid,p_m_u.received_by,tags.message_id
ORDER BY p_m_u.adddate DESC
How to resolve this.
Try using DISTINCT in your GROUP_CONCAT clause
GROUP_CONCAT( DISTINCT tags.tag SEPARATOR ';')
SELECT
p_m.*,
p_m_u.*,
GROUP_CONCAT(DISTINCT tags.tag SEPARATOR ';') AS 'MESSAGE_TAGS',
GROUP_CONCAT(DISTINCT linkdtl.link_id SEPARATOR ';') AS `LINK_ID`,
GROUP_CONCAT(DISTINCT linkdtl.link SEPARATOR ';') AS 'LINK',
GROUP_CONCAT(DISTINCT linkdtl.link_title SEPARATOR ';') AS 'LINK_TITLE' ....

MYSQL group_concat with and IF

Have a date field that I am getting out of my DB with the following;
PS Here is more of the query using a join to get the dates from the date table.
SELECT event,event_name,
GROUP_CONCAT(DATE_FORMAT(ed.date,'%b %e') ORDER BY ed.date SEPARATOR ',') as date2
FROM events ev
LEFT JOIN event_dates ed ON ev.eid=ed.eid
WHERE ev.yr='2013'
GROUP BY ev.eid
This produces this list of dates that takes up way to much space.
May 16,May 23,May 30,Jun 6,Jun 20
I want it to look like
May 16,23,30,Jun 6,20
Here is the query I tried. but it doesn't work because the sub-query doesn't seem to know the event id. guessing i might need to convert it to a join??
SELECT DISTINCT ev.event_id,
GROUP_CONCAT(DISTINCT DATE_FORMAT(race_date,'%a') ORDER BY race_date
SEPARATOR ', ') as date1,
(SELECT GROUP_CONCAT(dm) FROM
(SELECT CONCAT(
MONTHNAME(race_date),
' ',
GROUP_CONCAT(DAY(race_date) ORDER BY race_date)
) as dm
FROM event_dates ed1 WHERE ed1.event_id=ev.event_id
GROUP BY MONTH(race_date))as t) as date2
FROM events ev
JOIN event_dates ed ON ev.event_id = ed.event_id AND ev.race_year = ed.race_year
GROUP BY event_id
SELECT GROUP_CONCAT(d) FROM (
SELECT CONCAT(
MONTHNAME(date),
' ',
GROUP_CONCAT(DAY(date) ORDER BY date)
) AS d
FROM my_table
GROUP BY MONTH(date)
) t

mysql multiple-subquery group_concat query

I'm trying to show the boroughs and postcodes a particular town in is.
My database is fairly well structured, with a table such as town, postcode and borough. There are also tables for each of the relationships town_postcode & town_borough.
Ideally I want the data returned as:
"Abbey Wood", "SE2", "Bexley, Greenwich"
"Barbican", "EC1, EC2", "City of London"
I've tried a few different approaches and I'm close but not there yet.
Any help would be appreciated... :)
So far I've tried
SELECT DISTINCT t.town,
GROUP_CONCAT( DISTINCT p.postcode SEPARATOR ', ' ) AS 'postcode',
GROUP_CONCAT( DISTINCT b.borough SEPARATOR ', ' ) AS 'borough'
FROM coverage_towns AS t,
coverage_boroughs AS b,
coverage_postcodes AS p,
coverage_towns_boroughs AS tb,
coverage_towns_postcodes AS tp
WHERE t.id = tp.town_id
AND p.id = tp.postcode_id
AND b.id = tb.borough_id
GROUP BY t.town
ORDER BY t.town ASC
Which returns
"Abbey Wood", "SE2", "Southwark, Hammersmith and Fulham, Tower Hamlets, Wandsworth, Enfield, Newham, LOTS MORE HERE"
"Barbican", "EC1, EC2", "Brent, Greenwich, Kensington and Chelsea, Westminster, Camden, LOTS MORE HERE"
I've also tried
SELECT DISTINCT t.town, (
SELECT SQL_CACHE DISTINCT GROUP_CONCAT( p1.postcode
SEPARATOR ', ' )
FROM coverage_postcodes AS p1
WHERE p1.id = tp.postcode_id
) AS 'postcode', (
SELECT SQL_CACHE DISTINCT GROUP_CONCAT( b1.borough
SEPARATOR ', ' )
FROM coverage_boroughs AS b1
WHERE b1.id = tb.borough_id
) AS 'borough'
FROM coverage_towns AS t, coverage_boroughs AS b, coverage_postcodes AS p, coverage_towns_boroughs AS tb, coverage_towns_postcodes AS tp
WHERE t.id = tp.town_id
AND p.id = tp.postcode_id
AND b.id = tb.borough_id
GROUP BY t.town
ORDER BY t.town ASC
Which returns
"Abbey Wood", "SE2", "Greenwich"
"Acton", "W3", "Greenwich"
"Aldersbrook", "E12", "Greenwich"
First query looks good, just add distinct inside the group_concat, like:
SELECT t.town
, GROUP_CONCAT(DISTINCT p.postcode SEPARATOR ', ' ) AS 'postcode'
, GROUP_CONCAT(DISTINCT b.borough SEPARATOR ', ' ) AS 'borough'
<more code here>
GROUP BY
t.town
SOLUTION
I came back to the question after a good coffee and the answer presented itself.
SELECT DISTINCT t.town,
GROUP_CONCAT( DISTINCT p.postcode SEPARATOR ', ' ) AS 'postcode',
GROUP_CONCAT( DISTINCT b.borough SEPARATOR ', ' ) AS 'borough'
FROM towns AS t, boroughs AS b, postcodes AS p, towns_boroughs AS tb, towns_postcodes AS tp
WHERE (t.id = tp.town_id AND t.id = tb.town_id)
AND (p.id = tp.postcode_id AND b.id = tb.borough_id)
GROUP BY t.town
ORDER BY t.town ASC