Левый Соединить несколько раз 2 таблицы, используя один и тот же столбец - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть таблица A, в которой несколько значений столбцов должны быть заменены соответствующими идентификаторами, которые хранятся в таблице B, как в этой схеме:

TABLE_A
object_id   desc_id_1   desc_id_2   desc_id_3   desc_id_4   
zxy_34      9999        9567        5555        5556

TABLE_B
desc_id   complete_desc
1234      ABCD
9999      ZYXW
9567      POTG
5555      YUNR
5556      LPVR 
……..
……..

Финальное шоу, чем должно быть:

object    comp_desc_1  comp_desc_2  comp_desc_3  comp_desc_4
zxy_34    ZYXW         POTG         YUNR         LPVR

Возможно ли это?

На данный момент попробовал что-то подобное:

$sql="SELECT table_a.object_id, table_b.complete_desc 
FROM table_a 
LEFT JOIN table_b ON table_a.desc_id_1 =table_b.complete_desc";

Работает нормально, используя вывод таким образом:

echo "<table border='1'>
<tr>
<th>object</th>
<th>comp_desc_1 </th>
</tr>";

while($row = mysqli_fetch_array($result)) {
                                                echo "<tr>";
    echo "<td>" . $row['object_id '] . "</td>";
    echo "<td>" . $row['desc_id_1 '] . "</td>";
    echo "</tr>";
                                                }
echo "</table>";

Проблема в том, что вы не знаете, как идти дальше. При добавлении еще одного левого соединения остановите скрипт и загрузите пустую страницу:

$sql="SELECT table_a.object_id, table_b.complete_desc, table_b.complete_desc 
FROM table_a 
LEFT JOIN table_b ON table_a.desc_id_1 =table_b.complete_desc
LEFT JOIN table_b ON table_a.desc_id_2 =table_b.complete_desc ";

…..

echo "<table border='1'>
<tr>
<th>object</th>
<th>comp_desc_1 </th>
<th>comp_desc_2 </th>
</tr>";

while($row = mysqli_fetch_array($result)) {
                                                echo "<tr>";
    echo "<td>" . $row['object_id '] . "</td>";
    echo "<td>" . $row['desc_id_1 '] . "</td>";
    echo "<td>" . $row['desc_id_2'] . "</td>";
    echo "</tr>";
                                                }
echo "</table>";

Кто-нибудь может мне помочь?

Ответы [ 3 ]

0 голосов
/ 06 ноября 2018

Чтобы получить то, что вы хотите, соединения должны быть на соответствующих идентификаторах, а затем получить соответствующее описание после объединения. Если заданный «ID» может отсутствовать, вам понадобится LEFT-JOIN, означающий все записи со стороны LEFT (первая таблица / псевдоним) независимо от совпадения справа (вторая таблица / псевдоним). Кроме того, полезно использовать псевдонимы, чтобы упростить читаемость, особенно для длинных имен таблиц или когда вам нужна одна и та же таблица несколько раз, например, в этом случае ...

select
      a.Object_ID,
      id1.complete_desc ID1Descript,
      id2.complete_desc ID2Descript,
      id3.complete_desc ID3Descript,
      id4.complete_desc ID4Descript
   from
      Table_A  a
         LEFT JOIN Table_B id1
            on a.desc_id_1 = id1.desc_id
         LEFT JOIN Table_B id2
            on a.desc_id_2 = id2.desc_id
         LEFT JOIN Table_B id3
            on a.desc_id_3 = id3.desc_id
         LEFT JOIN Table_B id4
            on a.desc_id_4 = id4.desc_id

Ваше присоединение никогда не будет иметь совпадения, такого как идентификационный номер, по сравнению с описанием. Вам нужен идентификатор из столбцов в вашей таблице Table_A, присоединенный к столбцу идентификатора в TableB, следовательно, несколько ссылок «псевдоним» для псевдонима «id1», «id2», «id3», «id4» ...

Кстати, пусть люди недовольны слишком большим количеством подчеркиваний для таблиц и / или столбцов. Привыкайте к CamelCaseColumnNaming vs Using_Underscore_For_Columns. Просто предложение ...

0 голосов
/ 06 ноября 2018

Важно, чтобы я убедил вас реструктурировать вашу таблицу "table_a". Он просто не настроен на выполнение чистых, эффективных и лаконичных запросов.

Для нормализации структуры я рекомендую следующие столбцы:

object_id
desc_id
desc_order

Тогда требуемый запрос "pivot" может быть выполнен всего одним левым соединением.

SELECT object_id,
       MAX(CASE WHEN desc_order = 1 THEN b.desc_id ELSE NULL END) AS desc_id1, 
       MAX(CASE WHEN desc_order = 2 THEN b.desc_id ELSE NULL END) AS desc_id2, 
       MAX(CASE WHEN desc_order = 3 THEN b.desc_id ELSE NULL END) AS desc_id3, 
       MAX(CASE WHEN desc_order = 4 THEN b.desc_id ELSE NULL END) AS desc_id4
FROM `table_a` a
LEFT JOIN `table_b` b ON a.desc_id = b.desc_id
GROUP BY `object_id`

SQLFIDDLE DEMO

Я могу только надеяться, что вы не слишком далеко продвинулись в своем проекте, чтобы внести эту корректировку, потому что это настроит вас на гораздо более легкое развитие в будущем. (Кроме того, улучшена гибкость - если вы решите, что вам нужно более 4 столбцов, вы можете легко включить 5 или более столбцов в набор результатов.

0 голосов
/ 06 ноября 2018

Вам необходимо присвоить каждому экземпляру table_b в вашем запросе псевдоним, в противном случае неизвестно, на какой экземпляр вы ссылаетесь. Вам также нужно присвоить отдельным complete_desc значениям разные имена, чтобы они не перезаписывали друг друга в выходном массиве. Попробуйте что-то вроде этого:

$sql="SELECT table_a.object_id, b1.complete_desc AS desc_id_1, b2.complete_desc AS desc_id_2
FROM table_a 
LEFT JOIN table_b b1 ON table_a.desc_id_1 = b1.complete_desc
LEFT JOIN table_b b2 ON table_a.desc_id_2 = b2.complete_desc ";

Вам также необходимо удалить пробелы в ключах массива в следующих строках:

echo "<td>" . $row['object_id '] . "</td>";
echo "<td>" . $row['desc_id_1 '] . "</td>";

они должны быть:

echo "<td>" . $row['object_id'] . "</td>";
echo "<td>" . $row['desc_id_1'] . "</td>";
...