mySQL GROUP_CONCAT IN JOIN - mysql

I have the following SQL. I am trying to perform a GROUP_CONCAT within a Join but no matter how I seem try it doesnt seem to work right.
Essentially there is a link tag table that does a one to many on another table that holds tags. So there might be say 8 tags for one article record. I need them concatenated together .vs. ending up with 8 records.
SELECT
`articles`.`art_title`,
`articles`.`art_bodytext`,
`info`.`inf_start_date`,
`info`.`inf_end_date`,
`info`.`inf_hits`,
`info`.`inf_acl`,
`category`.`name`,
`options`.`opt_tpl`,
`options`.`opt_published`,
`options`.`opt_options`,
`options`.`opt_acl`,
`tags`.`tag`
FROM
`linktable`
INNER JOIN `articles` ON (`linktable`.`lnk_data_id` = `articles`.`art_id`)
INNER JOIN `info` ON (`articles`.`art_info_id` = `info`.`inf_id`)
INNER JOIN `category` ON (`articles`.`art_cat_id` = `category`.`id`)
AND (`articles`.`art_cat_tree_id` = `category`.`fid`)
INNER JOIN `options` ON (`articles`.`art_opt_id` = `options`.`opt_id`)
INNER JOIN `linktags` ON (`articles`.`art_tag_set_id` = `linktags`.`lnk_tagset_id`)
LEFT OUTER JOIN GROUP_CONCAT(`tags`) ON (`linktags`.`lnk_tag_id` = `tags`.`tag_id`)
WHERE
`linktable`.`lnk_pgc_id` = 1

Move the GROUP_CONCAT() into the field list, it is not a join condition, but a field calculation.
Add a GROUP BY to find the rows to combine
This gives
SELECT
`articles`.`art_title`,
`articles`.`art_bodytext`,
`info`.`inf_start_date`,
`info`.`inf_end_date`,
`info`.`inf_hits`,
`info`.`inf_acl`,
`category`.`name`,
`options`.`opt_tpl`,
`options`.`opt_published`,
`options`.`opt_options`,
`options`.`opt_acl`,
GROUP_CONCAT(`tags`.`tag`) AS tags
FROM
`linktable`
INNER JOIN `articles` ON (`linktable`.`lnk_data_id` = `articles`.`art_id`)
INNER JOIN `info` ON (`articles`.`art_info_id` = `info`.`inf_id`)
INNER JOIN `category` ON (`articles`.`art_cat_id` = `category`.`id`)
AND (`articles`.`art_cat_tree_id` = `category`.`fid`)
INNER JOIN `options` ON (`articles`.`art_opt_id` = `options`.`opt_id`)
INNER JOIN `linktags` ON (`articles`.`art_tag_set_id` = `linktags`.`lnk_tagset_id`)
LEFT JOIN `tags` ON (`linktags`.`lnk_tag_id` = `tags`.`tag_id`)
WHERE
`linktable`.`lnk_pgc_id` = 1
GROUP BY `articles`.`art_id`

Related

error subquery return more than 1 when doing multiple select

I want to do a multiple select in one query with different conditions. but somehow i'm stuck in this problem. any idea?
SELECT
(select io_link_event_names.name from doors left join controller_devices on doors.iid = controller_devices.iid left join events on controller_devices.mac = events.mac left join io_link_event_names on events.iolinkerid = io_link_event_names.extra where events.iolinkerid = "9000;1") AS forced,
(select doors.name FROM doors) AS doorname
ERROR #1242 - Subquery returns more than 1 row
consider this
SELECT d.[forced], doors.name as doorname
from doors
left join (
select controller_devices.iid, io_link_event_names.name as [forced]
from events
inner join controller_devices on controller_devices.mac = events.mac
inner join io_link_event_names on events.iolinkerid = io_link_event_names.extra
where events.iolinkerid = "9000;1"
) as d on d.iid = doors.iid
If you have more than 1 row in table doors, you get this error. If you want too see door name relevant to event selected in first query, use
select io_link_event_names.name,
doors.name doorname
from doors
left join controller_devices
on doors.iid = controller_devices.iid
left join events
on controller_devices.mac = events.mac
left join io_link_event_names
on events.iolinkerid = io_link_event_names.extra
where events.iolinkerid = "9000;1"

MySQL can’t specify target table for update in FROM multiple table joins

I have searched for days on how to get around this error while trying to update a field from a multiple join table, with a minimum date from the same mutiple join tableset.
This is my Update statement:
update vtiger_projectmilestone
Inner Join vtiger_projectmilestonecf ON vtiger_projectmilestone.projectmilestoneid = vtiger_projectmilestonecf.projectmilestoneid
Inner Join vtiger_crmentity ON vtiger_projectmilestone.projectmilestoneid = vtcrmm.crmid
inner join vtiger_project on vtiger_project.projectid = vtiger_projectmilestone.projectid
Inner Join vtiger_crmentity vtcrmp ON vtcrmp.crmid = vtiger_project.projectid
set vtiger_projectmilestone.projectmilestonedate =
(select min(vtiger_projecttaskcf.cf_779)
FROM vtiger_projecttask tvpt
Inner Join vtiger_projecttaskcf tvptcf ON tvpt.projecttaskid = tvptcf.projecttaskid
Inner Join vtiger_projectmilestone tvpm ON tvpm.projectmilestoneid = tvpt.projecttasknumber
Inner Join vtiger_projectmilestonecf vtpmcf ON tvpm.projectmilestoneid = tvpmcf.projectmilestoneid
Inner Join vtiger_crmentity AS vtcrmm ON tvpm.projectmilestoneid = vtcrmm.crmid
Inner Join vtiger_crmentity AS vtcrmt ON tvpt.projecttaskid = vtcrmt.crmid
where tvpm.projectmilestone_no = vtiger_projectmilestone.projectmilestone_no
)
where vtiger_projectmilestone.projectid =
(select vtiger_project.projectid from vtiger_project
INNER JOIN vtiger_crmentity vtcrmp ON vtiger_project.projectid = vtcrmp.crmid
where vtcrmp.deleted = 0 order by vtiger_project.projectid desc limit 1)
and vtcrmp.deleted = 0
and vtcrmm.deleted = 0
and (vtiger_projectmilestone.projectmilestonedate is null or vtiger_projectmilestonecf.cf_763 is null) ;
This is a real life update query, not just a simple one table relationship.
I got round it by creating a temp table, inserting the value, updating the destination table and dropping the temp table.
I would really like to get this right, because it will come up more often.
All assistance is appreciated.
Cheers
Bernard Bailey
As stated in this answer you can't use the target update table in a subquery, as you can see in your query
SELECT min(vtiger_projecttaskcf.cf_779)
FROM vtiger_projecttask tvpt
Inner Join vtiger_projecttaskcf tvptcf ON tvpt.projecttaskid = tvptcf.projecttaskid
Inner Join
--using target update table in query
vtiger_projectmilestone tvpm ON tvpm.projectmilestoneid = tvpt.projecttasknumber
Inner Join vtiger_projectmilestonecf vtpmcf ON tvpm.projectmilestoneid = tvpmcf.projectmilestoneid
Inner Join vtiger_crmentity AS vtcrmm ON tvpm.projectmilestoneid = vtcrmm.crmid
Inner Join vtiger_crmentity AS vtcrmt ON tvpt.projecttaskid = vtcrmt.crmid
where tvpm.projectmilestone_no = vtiger_projectmilestone.projectmilestone_no
However i think that a work around is using the data from the table that you're updating, so instead of using joins, you could write some where conditions for example:
SELECT min(vtiger_projecttaskcf.cf_779)
FROM vtiger_projecttask tvpt
Inner Join vtiger_projecttaskcf tvptcf ON tvpt.projecttaskid = tvptcf.projecttaskid
Inner Join vtiger_projectmilestonecf vtpmcf ON tvpm.projectmilestoneid = tvpt.projecttasknumber
Inner Join vtiger_crmentity AS vtcrmm ON tvpt.projecttasknumber = vtcrmm.crmid
Inner Join vtiger_crmentity AS vtcrmt ON tvpt.projecttaskid = vtcrmt.crmid
where tvpm.projectmilestone_no = vtiger_projectmilestone.projectmilestone_no
--using the projectmilestoneid in a where clause
AND tvpt.projecttasknumber=vtiger_projectmilestone.projectmilestoneid
The caveat could be that probably you will get some performance issues, also, as I don't know the full schema, I can't tell if using other tables in the subquery instead of vtiger_projectmilestone will give you the right result

SQL JOIN Query - linking four tables

I have the SQL to display ALL the activities and relative Admin permissions (if any) for that activity.
Current SQL Code:
SELECT `activities`.*, `admins`.`admin_role_id`
FROM (`activities`)
LEFT JOIN `admins` ON `admins`.`activity_id`=`activities`.`id` AND admins.member_id=27500
WHERE `activities`.`active` = 1
Returning:
id | name | description | active | admin_role_id (or null)
I then need to detect whether they are an active member within that Activity.
I have the following SQL code:
SELECT DISTINCT `products`.`activity_ID` as joinedID
FROM (`transactions_items`)
JOIN `transactions` ON `transactions`.`id` = `transactions_items`.`id`
JOIN `products` ON `products`.`id` = `transactions_items`.`product_id`
JOIN `activities` ON `activities`.`id` = `products`.`activity_ID`
WHERE `transactions`.`member_id` = 27500
AND `activities`.`active` = 1
Is there any way to merge this into one SQL query. I can't figure out how to use the correct JOIN queries, because of the complexity of the JOINs.
Help please, thanks! :)
Try like this
SELECT `activities`.*, `admins`.`admin_role_id`
FROM (`activities`)
LEFT JOIN `admins` ON `admins`.`activity_id`=`activities`.`id` AND admins.member_id=27500
JOIN (`transactions_items`
JOIN `transactions` ON `transactions`.`id` = `transactions_items`.`id`
JOIN `products` ON `products`.`id` = `transactions_items`.`product_id`)
ON `activities`.`id`=`products`.`activity_ID`
WHERE `transactions`.`member_id` = 27500
AND `activities`.`active` = 1
Seems to me that a query like this would be marginally more comprehensible and (I think) adhere more closely to the spec...
SELECT c.*
, d.admin_role_id
FROM activities c
LEFT
JOIN admins d
ON d.activity_id = c.id
AND d.member_id = 27500
LEFT
JOIN products p
ON p.activity_ID = c.id
LEFT
JOIN transactions_items ti
ON ti.product_id = p.id
LEFT
JOIN transactions t
ON t.id = ti.id
AND t.member_id = 27500
WHERE c.active = 1

SQL query wrong result

i have this query:
SELECT `completed`.`ID` AS `ID`,`completed`.`level` AS `level`,`completed`.`completed_in` AS `completed_in`, COUNT(1) AS `right_answers_num`
FROM `completed`
INNER JOIN `history` ON `history`.`ID` = `completed`.`ID`
INNER JOIN `questions` ON `questions`.`ID` = `history`.`question`
WHERE `completed`.`student_id` = '1' AND `questions`.`answer` = `history`.`answer`
GROUP BY `completed`.`ID`
ORDER BY `completed`.`completed_in` DESC
what i need is to get info of each test in completed table (id,level,completed_in,right_answer_num)
the problem with that query is that if there is no one right answer(history.answer = questions.answer) then it doesn't return the row, while it should return the row(id,level,completed_in) and the right_answer_num(counter) should be zero..
please help me,, thanks ahead.
SELECT
completed.ID AS ID,
completed.level AS level,
completed.completed_in AS completed_in,
COUNT(questions.answer) AS right_answers_num
FROM completed
INNER JOIN history ON history.ID = completed.ID
LEFT JOIN questions ON questions.ID = history.question AND questions.answer = history.answer
WHERE
completed.student_id = '1'
GROUP BY
completed.ID
ORDER BY completed.completed_in DESC
use a LEFT OUTER JOIN intead of an INNER JOIN.
The second inner join is what's causing rows with no record in the questions table to be omitted. An inner join will only return rows that have data in all corresponding tables. Change the second inner join to a left join like so:
SELECT
completed.ID AS ID,
completed.level AS level,
completed.completed_in AS completed_in,
COUNT(questions.answer) AS right_answers_num
FROM completed
INNER JOIN history ON history.ID = completed.ID
LEFT JOIN questions ON questions.ID = history.question
WHERE completed.student_id = 1
GROUP BY completed.ID
ORDER BY completed.completed_in DESC

Trying to add a subquery to a join query

I have a query like this
SELECT
tbl_products.*,
GROUP_CONCAT(tags.name)
FROM
tbl_page_collections_products,
(SELECT page_collection_name as name
FROM tbl_page_collections
LEFT JOIN tbl_pages ON tbl_page_collections.page_id = tbl_pages.page_id
WHERE tbl_pages.page_name LIKE '%friends%') tags
LEFT JOIN tbl_page_collections
ON tbl_page_collections.page_collection_id = tbl_page_collections_products.colID
LEFT JOIN tbl_pages
ON tbl_page_collections.page_id = tbl_pages.page_id
LEFT JOIN tbl_products
ON tbl_products.product_id = tbl_page_collections_products.product
WHERE
tbl_pages.page_name LIKE '%friends%'
The error I get is Unknown column 'tbl_page_collections_products.colID in on clause but I don't get that error when the subquery isn't there and that column exists in that table.
Is something conflicting?
tbl_page_collections_products is not in you subquery from clause. Maybe this is what you want:
SELECT
tbl_products.*,
GROUP_CONCAT(tags.name)
FROM
tbl_products,
(SELECT page_collection_name as name
FROM tbl_page_collections
,tbl_page_collections_products
LEFT JOIN tbl_pages ON tbl_page_collections.page_id = tbl_pages.page_id
WHERE tbl_pages.page_name LIKE '%friends%') tags
LEFT JOIN tbl_page_collections
ON tbl_page_collections.page_collection_id = tbl_page_collections_products.colID
LEFT JOIN tbl_pages
ON tbl_page_collections.page_id = tbl_pages.page_id
LEFT JOIN tbl_products
ON tbl_products.product_id = tbl_page_collections_products.product
WHERE
tbl_pages.page_name LIKE '%friends%'