问题
I am trying to do a fairly complex (for me) query that will grab a Description field from a Main Table and then append it with titles and values from related Look-Up-Tables. Not all records have records in the Look-up tables. I'll pose further questions as subsequent questions as I go along, but to start my issue is that only those records with values in all the tables show up.
http://sqlfiddle.com/#!9/09047/13
- (null)
- This is Record 2 Text
Color:
Red
Fruit:
Apple - (null)
If I use Concat_WS I get all records but my 'label' in the concat disappears:
http://sqlfiddle.com/#!9/09047/16
- This is Record 1 Text
Blue - This is Record 2 Text
Red
Apple - This is Record 3 Text
Grape
So my first step is to get all the record descriptions regardless of how many Look-up-Tables they exist in and to get the Names/Labels displaying.
回答1:
It looks like you need COALESCE
:
Select J.id,
Concat(J.Description,
COALESCE(Concat('<b>Color</b>:<br>',
group_concat(F.Name SEPARATOR '<br>')),''),
'<br>',
COALESCE(Concat('<b>Fruit</b>:<br>',
group_concat(F2.Name SEPARATOR '<br>')),'')
) AS output
from Main J
Left Join LUT_1 L On J.ID=L.MainID
Left Join LUT_Names_1 F On F.ID=L.LUT_NAME_ID
Left Join LUT_2 L2 On J.ID=L2.MainID
Left Join LUT_Names_2 F2 On F2.ID=L2.LUT_NAME_ID
Group by J.ID;
SQLFiddle Demo
EDIT:
As always for MySQL, the query itself is basing on MySQL extension. If you set it to ONLY_FULL_GROUP_BY (default for MySQL 5.7.5 and above):
SET sql_mode=ONLY_FULL_GROUP_BY;
-- query will return error
J.Description' isn't in GROUP BY
To correct this you will need to use aggregation function on that column like: MAX:
SET sql_mode=ONLY_FULL_GROUP_BY;
Select J.id,
Concat(MAX(J.Description),
COALESCE(Concat('<b>Color</b>:<br>',
group_concat(F.Name SEPARATOR '<br>')),''),
'<br>',
COALESCE(Concat('<b>Fruit</b>:<br>',
group_concat(F2.Name SEPARATOR '<br>')),'')
)
from Main J
Left Join LUT_1 L On J.ID=L.MainID
Left Join LUT_Names_1 F On F.ID=L.LUT_NAME_ID
Left Join LUT_2 L2 On J.ID=L2.MainID
Left Join LUT_Names_2 F2 On F2.ID=L2.LUT_NAME_ID
Group by J.ID;
回答2:
I think the concat_ws()
may be throwing off what you want to do.
The following produces the two labels, even when there are no values:
Select J.id,
Concat(J.Description,
'<br><br>',
'<b>Color</b>:<br>',
coalesce(group_concat(F.Name SEPARATOR '<br>'), ''),
'<br>',
'<b>Fruit</b>:<br>',
coalesce(group_concat(F2.Name SEPARATOR '<br>'), '')
)
from Main J Left Join
LUT_1 L
On J.ID = L.MainID Left Join
LUT_Names_1 F
On F.ID = L.LUT_NAME_ID Left Join
LUT_2 L2
On J.ID = L2.MainID Left Join
LUT_Names_2 F2
On F2.ID = L2.LUT_NAME_ID
Group by J.ID, J.Description;
Here is a SQL Fiddle.
In addition, if you have multiple fruits or colors, you are going to get duplicates. For this reason, you want the distinct
keyword (or to pre-aggregate along each dimension). So the working SQL is more like this:
Select J.id,
Concat(J.Description,
'<br><br>',
'<b>Color</b>:<br>',
coalesce(group_concat(distinct F.Name SEPARATOR '<br>'), ''),
'<br>',
'<b>Fruit</b>:<br>',
coalesce(group_concat(distinct F2.Name SEPARATOR '<br>'), '')
)
from Main J Left Join
LUT_1 L
On J.ID = L.MainID Left Join
LUT_Names_1 F
On F.ID = L.LUT_NAME_ID Left Join
LUT_2 L2
On J.ID = L2.MainID Left Join
LUT_Names_2 F2
On F2.ID = L2.LUT_NAME_ID
Group by J.ID, J.Description
Here is a SQL Fiddle that illustrates this point. Just remove the distinct
and see the difference in the results.
来源:https://stackoverflow.com/questions/49348902/multiple-table-joins-with-group-concat-where-some-records-dont-exist-in-all-tab