For easier explaination I will try to simplify everything. 

I have 3 SQL tables: `Users`, `Certs`, `Serv`

In `Users` table are stored details about unique users.

In `Certs` table are stored details about certificates and `UserId` of user who have this certificate (1 user can have multiple certificates)

In `Serv` table are stored details about sea services and `UserId` of user (like `Certs` table, 1 user can have multiple entries in `Serv` table)

**SAMPLE DATA**

Users 

```
UserId  Name
1       John
2       Lisa

```

Certs

```
Id  UserId  CertName
1   1       A
2   1       B
3   1       C
4   2       A
5   2       C

```

Serv

```
UserId  Name
1       SA
1       SB
1       SC
1       SD
2       S2A

```

I need to retrieve output via PHP something like (where UserId = 1) also for reality there will be more columns from each table (for example more details of certificates like date of issue, date of expire, place of issue and so on):

```
Personal details:
Name
John

Certificates:
Certificate Id    Certificate Name
1                 A 
2                 B
3                 C

Sea Services:
Sea Service Name
SA
SB
SC
SD

```

But I got wrong output, duplicated entries, that because joining 2 tables with `UserId` in whose are multiple records with this `UserId`.

**PHP CODE**

```
$users = $con->prepare("
    select u.Name 
           ,GROUP_CONCAT(c.Id SEPARATOR '<br>') AS Id
           ,GROUP_CONCAT(c.certsName SEPARATOR '<br>') AS certsName 
           ,GROUP_CONCAT(s.Name SEPARATOR '<br>') AS Name         
    from users u
    left join certs c on u.UserId = c.UserId
    left join serv s on u.UserId = s.UserId 
    where u.UserId = ?
");
$users->bind_param('i', $GetUserId);
$users->execute();

$users->bind_result(
    $userName,
    $certId,            
    $certName,          
    $servName
);

<?php 
while ($users->fetch()) {
?>

<span>Personal Details</span>
<div class="grid-group">
    <div class="grid-column">
        <div class="grid-item header">User Name </div> 
    </div>
    <div class="grid-column">
        <div class="grid-item"><?php echo $userName; ?></div>       
    </div>
</div>

<span>Certificates</span>
<div class="grid-group">
    <div class="grid-column">
        <div class="grid-item header">Certificate Id</div> 
        <div class="grid-item header">Certificate Name</div> 
    </div>
    <div class="grid-column">
        <div class="grid-item"><?php echo $certId; ?></div> 
        <div class="grid-item"><?php echo $certName; ?></div>       
    </div>
</div>

<span>Sea Services</span>
<div class="grid-group">
    <div class="grid-column">
        <div class="grid-item header">Sea Service Name</div> 
    </div>
    <div class="grid-column">
        <div class="grid-item"><?php echo $servName; ?></div>       
    </div>
</div>

<?php } ?>

```

You can check [**SQL FIDDLE**](http://sqlfiddle.com/#!9/e1ef4a/2) to see what results selecting, duplicating rows. 

Have you ideas how can I achieve desired output without duplicates?

**UPDATE**

After using `GROUP_CONCAT` with `DISTINCT` It's still wrong. Imagine that In `Serv` table I have columns like: `UserId`, `Name`, `Rank` and `Country`

If the same user worked in different companies (this Name in example - Company Name) with the same rank in different countries, It selecting wrong data. For example:

Serv table (SQL)

```
UserId  Name     Rank        Country
1       SA       Captain     USA
1       SB       Captain     USA
1       SC       Captain     RUS
1       SD       Captain     ENG
2       S2A      Engineer    USA 

```

If I use query like this:

```
select u.Name 
       ,GROUP_CONCAT(distinct c.Id SEPARATOR '<br>') AS Id
       ,GROUP_CONCAT(distinct c.certsName SEPARATOR '<br>') AS certsName 
       ,GROUP_CONCAT(distinct s.Name SEPARATOR '<br>') AS Name  
       ,GROUP_CONCAT(distinct s.Rank SEPARATOR '<br>') AS Rank
       ,GROUP_CONCAT(distinct s.Country SEPARATOR '<br>') AS Country        
from users u
left join certs c on u.UserId = c.UserId
left join serv s on u.UserId = s.UserId 
where u.UserId = ?

```

So `GROUP_CONCAT(DISTINCT..)` returning me in following:

```
......
Sea Services:
Sea Service Name    Rank      Country
SA                  Captain   USA
SB                            RUS
SC                            ENG
SD                        

```

Only first row have rank and first 3 rows have countries returned, but in database are stored ranks and countries for every row.

Full desired output with this data should be like this:

```
Personal details:
Name
John

Certificates:
Certificate Id    Certificate Name
1                 A 
2                 B
3                 C

Sea Services:
Sea Service Name    Rank      Country
SA                  Captain   USA
SB                  Captain   USA             
SC                  Captain   RUS
SD                  Captain   ENG

```

You can check It at [**SQL FIDDLE**](http://sqlfiddle.com/#!9/1ab01/1)

**UPDATE 2**

If I remove `DISTINCT` I got following output:

```
Sea Service Name    Rank        Country
SA                  Captain     USA
SA                  Captain     USA
SA                  Captain     USA
SB                  Captain     USA
SB                  Captain     USA
SB                  Captain     USA
SC                  Captain     RUS
SC                  Captain     RUS
SC                  Captain     RUS
SD                  Captain     ENG
SD                  Captain     ENG
SD                  Captain     ENG

```

If I'm using `DISTINCT` I got like this:

```
Sea Services:
Sea Service Name    Rank      Country
SA                  Captain   USA
SB                            RUS
SC                            ENG
SD                        

```

But It should be:

```
Sea Services:
Sea Service Name    Rank      Country
SA                  Captain   USA
SB                  Captain   USA             
SC                  Captain   RUS
SD                  Captain   ENG

```

**UPDATE 3**

Imagine that I have fixed width of columns and I have long Sea Service Name which will be wrapped to new row:

```
Sea Service Name |  Rank  | Country
-----------------|--------|---------
This is long Sea | Captain| USA
Service Name     |--------|---------
-----------------| Captain| RUS
 Other Name      |--------|---------
-----------------| Captain| ENG
Another long Sea |--------|---------
Service Name     | Master | USA                        
-----------------|--------|---------
Other Sea Serv   |
-----------------|

```

As you see now each column are separate, rows didn't match. But It should be like 1 row. So I think I can't achieve It with `GROUP_CONCAT`, looks like I need another way.

How It looks in real:

[![rows not match](https://i.stack.imgur.com/0pOOS.png)](https://i.stack.imgur.com/0pOOS.png)