简体   繁体   中英

MySql join multiple tables with different rows number

I'm sorry for the probably confusing title but I didn't really know how to describe my problem well. I also appologize for my english as I'm not a native speaker.

Let's say I have this schema :

 _________                               _________
| Table 1 |                             | Table 2 |
|---------|          ______     ________|---------|
| id_a    |___      | join |   |        | id_b    |
| name    |   |     |------|   |        | info    |
|_________|   |_____| id_a |___|        | data    |
                    | id_b |            |_________|
                    |______|

With these informations in the database :

Table 1 :

 _____________
| id_a | name |
|------|------|
|   1  | foo  |
|______|______|

Table 2 :

 _____________________
| id_b | info | data  |
|------|------|-------|
|   1  | bar  | baz   |
|   2  | kux  | corge |
|   3  | fred | quux  |
|______|______|_______|

Join :

 _____________
| id_a | id_b |
|------|------|
|   1  |   1  |
|   1  |   2  |
|   1  |   3  |
|______|______|

In my database, I have other tables that are the same type as the "Join" one. They are used to store a "Table 1" ID and other IDs from other tables (I used only one join table in my schema to simplify the problem) .

When I tried to retrive the datas that I wanted, I first used this syntax :

SELECT t1.*,
       t2.*
FROM table1 AS t1
LEFT JOIN join AS j
ON j.id_a = t1.id_a
LEFT JOIN table2 AS t2
ON t2.id_b = j.id_b
WHERE t1.id_a = ?

But as the result was an array of multiple rows while I was expecting only one single row, I tried then to use GROUP_CONCAT .

So my syntax became :

SELECT t1.*,
       GROUP_CONCAT(t2.info SEPARATOR '|') AS info,
       GROUP_CONCAT(t2.data SEPARATOR '|') AS data
FROM table1 AS t1
LEFT JOIN join AS j
ON j.id_a = t1.id_a
LEFT JOIN table2 AS t2
ON t2.id_b = j.id_b
WHERE t1.id_a = ?
GROUP BY t1.id_a

Now it works fine and it returns a single row.

The problem now is that I'm using this principle with multiple joins and each join returns multiple rows of a different number than the others. The concatenation value is then duplicated and I can have results such as :

arrray(
    [...]
    'info' => 'bar|bar|bar|bar|kux|kux|kux|kux|fred|fred|fred|fred|',
    'data' => 'baz|baz|baz|baz|corge|corge|corge|corge|corge|quux|quux|quux|quux'
)

So I would like to know if there is a way to avoid duplicated values and still retrieve the datas that I want in a single request ?

Given your data, this query should be returning what you want:

SELECT t1.*,
       GROUP_CONCAT(t2.info SEPARATOR '|') AS info,
       GROUP_CONCAT(t2.data SEPARATOR '|') AS data
FROM table1 t1 LEFT JOIN
     join j
     ON j.id_a = t1.id_a LEFT JOIN
     table2 t2
     ON t2.id_b = j.id_b
WHERE t1.id_a = ?
GROUP BY t1.id_a;

If you want, you can remove the duplicates using DISTINCT :

SELECT t1.*,
       GROUP_CONCAT(DISTINCT t2.info SEPARATOR '|') AS info,
       GROUP_CONCAT(DISTINCT t2.data SEPARATOR '|') AS data
FROM table1 t1 LEFT JOIN
     join j
     ON j.id_a = t1.id_a LEFT JOIN
     table2 t2
     ON t2.id_b = j.id_b
WHERE t1.id_a = ?
GROUP BY t1.id_a;

Typically, though, it is better to fix the query so it doesn't generate the duplicates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM