MySQL: GROUP_CONCAT with LEFT JOIN
Use:
SELECT t.*,
x.combinedsolutions
FROM TICKETS t
LEFT JOIN (SELECT s.ticket_id,
GROUP_CONCAT(s.soution) AS combinedsolutions
FROM SOLUTIONS s
GROUP BY s.ticket_id) x ON x.ticket_id = t.ticket_id
Alternate:
SELECT t.*,
(SELECT GROUP_CONCAT(s.soution)
FROM SOLUTIONS s
WHERE s.ticket_id = t.ticket_id) AS combinedsolutions
FROM TICKETS t
mysql left join with group_concat - only shows a single result
You are describing a left join
:
select
a.accountID,
a.accountOpenedDate,
a.accountStatus,
group_concat(e.expenseType separator ':') as expense
from account a
left join expense e on e.accountID = a.accountID
group by a.accountID
order by a.accountID
I also don't see the point for expression MONTH(DATE(AccountOpenedDate))
in the GROUP BY
clause: you seem to want one row per account, so this seems irrelevant.
The above query works under the assumption that accountID
is the primary key of table account
: other columns from the same column are functionaly dependent on the primary key, so you do not need to list them in the group by
clause. You could also write this as:
select
a.accountID,
a.accountOpenedDate,
a.accountStatus,
group_concat(e.expenseType separator ':') as expense
from account a
left join expense e on e.accountID = a.accountID
group by a.accountID, a.accountOpenedDate, a.accountStatus
order by a.accountID
Side notes:
table aliases make the query easier to write and read
in a multi-table query, all columns should be qualified (prefixed) with the (alias of the) table they belong to
Using group_concat in left join
You need group by
in the subquery:
SELECT *
FROM wp_fishy_posts p LEFT JOIN
(SELECT GROUP_CONCAT(i.path,',') AS linked_images, l.postID as link_id
FROM wp_fishy_images i LEFT JOIN
wp_fishy_images_post_link l
ON l.imageID = i.ID
GROUP BY l.postId
------^
) l
ON l.link_id = p.ID
WHERE p.post_type = 'image';
GROUP_CONCAT with multiple LEFT JOINs
Try to split the query into the two and then perform the join
SELECT c.*, t2.modulepath, t1.subassemblypath
FROM connectors c
JOIN (
SELECT
s.cid,
GROUP_CONCAT(s.subassemblypath SEPARATOR "|") AS subassemblypath
FROM subassemblies s
GROUP BY s.cid
) t1 ON c.id = t1.cid
JOIN
(
SELECT
m.cid,
GROUP_CONCAT(m.modulepath SEPARATOR "|") AS modulepath
FROM modules m
GROUP BY m.cid
) t2 ON c.id = t2.cid
MYSQL CONCAT + GROUP_CONCAT + LEFT OUTER JOIN
With a MySQL version prior to 5.7.22 you can't use the JSON built-in functions.
You'll have to use a few imbricated GROUP_CONCAT subqueries to obtain your JSON string.
As told in the comments, your expected JSON string is not valid. The following answer will differ from your expected result, to fix this issue.
I suggest you proceed with a first query to get a column with the "aeroport" names, and another column with the associated stations formatted as a list, for each couple of "rule.id + aeroport_name".
This gives the following query:
mysql> select rules.id, name, concat ('"', aeroport, '":') as aeroport_name, group_concat('"', station, '"') as station_list
-> from rules
-> inner join pivot on rules.id = pivot.id_rule
-> inner join transferts on pivot.id_transfert = transferts.id
-> group by rules.id, aeroport_name;
+------+------+---------------+---------------------+
| id | name | aeroport_name | station_list |
+------+------+---------------+---------------------+
| 1 | a | "GNB": | "La Tania" |
| 1 | a | "GVA": | "Flaine" |
| 2 | b | "GNB": | "La Tania","Flaine" |
| 2 | b | "GVA": | "Flaine" |
+------+------+---------------+---------------------+
4 rows in set (0,00 sec)
Then, we are going to use this query as a subquery to associate each "station_list" to its given aeroport, in a rule id context, within a single string.
This give the following encapsulation:
mysql> select id, name, group_concat(aeroport_name, '[', station_list, ']') as aeroport_list
-> from (
-> select rules.id, name, concat ('"', aeroport, '":') as aeroport_name, group_concat('"', station, '"') as station_list
-> from rules
-> inner join pivot on rules.id = pivot.id_rule
-> inner join transferts on pivot.id_transfert = transferts.id
-> group by rules.id, aeroport_name
-> ) as isolated group by id;
+------+------+----------------------------------------------+
| id | name | aeroport_list |
+------+------+----------------------------------------------+
| 1 | a | "GNB":["La Tania"],"GVA":["Flaine"] |
| 2 | b | "GNB":["La Tania","Flaine"],"GVA":["Flaine"] |
+------+------+----------------------------------------------+
2 rows in set (0,00 sec)
And finally, we can now add the final "{}" encapsulation to our string, by adding a top level query over this:
mysql> select id, name, concat('{', aeroport_list, '}') as conf
-> from (
-> select id, name, group_concat(aeroport_name, '[', station_list, ']') as aeroport_list
-> from (
-> select rules.id, name, concat ('"', aeroport, '":') as aeroport_name, group_concat('"', station, '"') as station_list
-> from rules
-> inner join pivot on rules.id = pivot.id_rule
-> inner join transferts on pivot.id_transfert = transferts.id
-> group by rules.id, aeroport_name
-> ) as isolated group by id
-> ) as full_list;
+------+------+------------------------------------------------+
| id | name | conf |
+------+------+------------------------------------------------+
| 1 | a | {"GNB":["La Tania"],"GVA":["Flaine"]} |
| 2 | b | {"GNB":["Flaine","La Tania"],"GVA":["Flaine"]} |
+------+------+------------------------------------------------+
2 rows in set (0,01 sec)
GROUP CONCAT and LEFT OUTER JOIN to split
You need two levels of aggregation: one by building_id
and another by site_id
.
with b_l as (
select
b.id as building_id
, b.site_id
, concat('('
, group_concat(
l.id
order by l.id
separator ','
)
, ')'
) as building_levels
from buildings as b
left join levels as l
on b.id = l.building_id
group by b.id, b.site_id
)
, s_b as (
select
s.id
, group_concat(
b_l.building_id
order by b_l.building_id
separator ','
) as buildings
, group_concat(
b_l.building_levels
order by b_l.building_id
separator ','
) as levels
from sites as s
left join b_l
on s.id = b_l.site_id
group by s.id
)
select *
from s_b
id | buildings | levels
-: | :-------- | :----------------------
1 | 1,2,3 | (1,2),(3,4,5),(6)
2 | 4,5,6 | (7,8),(9),(10,11)
3 | 7,8,9 | (12,13,14),(15,16),(17)
4 | 10 | null
Or the same with lateral join:
select
s.id
, group_concat(
b_l.building_id
order by b_l.building_id
separator ','
) as buildings
, group_concat(
b_l.building_levels
order by b_l.building_id
separator ','
) as levels
from sites as s
left join lateral (
select
b.site_id
, b.id as building_id
, concat('('
, group_concat(
l.id
order by l.id
separator ','
)
, ')'
) as building_levels
from buildings as b
left join levels as l
on b.id = l.building_id
group by b.id, b.site_id
) b_l
on s.id = b_l.site_id
group by s.id
db<>fiddle here
How can I change a group_concat column that's left joined with another table to empty string instead of null when there are no matching records?
Wrap the result with IFNULL will do.
SELECT u.*, IFNULL(GROUP_CONCAT(pps.photo_key ORDER BY pps.is_primary DESC), '') as photo_keys
FROM users u
LEFT JOIN profile_images pps ON u.id=pps.user_id
WHERE u.id = "555555555"
GROUP BY u.id`
GROUP_CONCAT with LEFT JOIN condition?
Storing comma separated ids is not a good idea see Database Normalization,you cannot simply use IN()
to join with your set column for now you need to use FIND_IN_SET to find the values in a comma separated set
SELECT
GROUP_CONCAT(pr.id ORDER BY pr.id) AS promo_ids,
p.id AS product_id,
p.name AS product_name
FROM
`products` AS p
LEFT JOIN `promos` AS pr
ON FIND_IN_SET(`p`.`id`,pr.product_ids)
WHERE p.category_id IN (1, 2, 3, 4)
GROUP BY p.id
Mysql group_concat(id) as ids in a left join and using ids to select all columns in id group
The simple fix would appear to be to use FIND_IN_SET for the join. But this is a bit of a hack and will not be that quick.
SELECT *
FROM `view_test`
INNER JOIN
(
SELECT GROUP_CONCAT(DISTINCT entity_id) AS idsgroup
FROM `view_test`
WHERE (attribute_name = 'sku')
GROUP BY value_name
LIMIT 0, 3
) bind
ON FIND_IN_SET(entity_id, bind.idsgroup);
Further not sure why you have a LIMIT on the sub query, especially without an order clause.
Possibly better to use a sub query to just get the DISTINCT entity_id with an attribute_name of sku and join against that.
SELECT *
FROM `view_test`
INNER JOIN
(
SELECT DISTINCT entity_id
FROM `view_test`
WHERE (attribute_name = 'sku')
) bind
ON view_test.entity_id = bind.entity_id
Related Topics
Window Functions or Common Table Expressions: Count Previous Rows Within Range
How to Rename Something in SQL Server That Has Square Brackets in the Name
How to Alter This Computed Column in SQL Server 2008
Why Doesn't SQL Support "= Null" Instead of "Is Null"
Postgresql Generate Sequence with No Gap
Reference an Alias Elsewhere in the Select List
Which Database Design Gives Better Performance
Inner Join in Update SQL for Db2
Why Postgres Returns Unordered Data in Select Query, After Updation of Row
How to Fill Date Gaps in MySQL
Why Using a Udf in a SQL Query Leads to Cartesian Product
Parameterise Table Name in .Net/Sql
I Keep Getting the Error "Relation [Table] Does Not Exist"
Postgres - Where in (List) - Column Does Not Exist
Incomplete Information from Query on Pg_Views