Distinguish equal fields in a SELECT with LEFT JOIN

Asked

Viewed 686 times

2

In a SELECT done in two tables with similar fields I would like to distinguish the field of each table when displaying the results. For example:

$sql = BD::conn()->prepare("SELECT a.*, b.*
                                FROM tabela_a a
                                LEFT JOIN tabela b ON
                                a.campo = b.campo");
$sql->execute();
$dados = $sql->fetch();

Let’s imagine that in both tables I have the field data and I would like to show the field of each distinguished:

 $dados["a.data"] ou $dados["b.data"]

When giving a print_r in $dados the keys of the array are named by table a, while the columns of table b that are equal to those of table a are enumerated crescently as a common array, there is some way to display the data of each separate one?

Note: to minimize the question I did not ask while in research

2 answers

2


You will need to name these specific columns manually to be able to "pick them up" after the while.

Example

$sql = BD::conn()->prepare(
    "SELECT 
    a.campo1, a.campo2, a.campo3, a.campo_igual as a_campo_igual,
    b.campo1, b.campo2, b.campo3, b.campo_igual as b_campo_igual
    FROM tabela_a a
    LEFT JOIN tabela b ON a.campo = b.campo"
);

If you want to add the table as a prefix for each column

So you can take the "equal fields" without problem in while.

// array para informar qual coluna pertence a qual tabela
// irei processar isso depois para formar o apelido "tabela_x_coluna_y"
// é muito provável que este array seja preciso montar manualmente, 
// mas irá facilitar sua vida no SELECT
$tabelas = [
    'tabela_a' => [
        'campo1',
        'campo2',
        'campo3',
        'campo_igual',
    ],
    'tabela_b' => [
        'campo1',
        'campo2',
        'campo3',
        'campo_igual',
    ]
];

// array com as colunas apelidadas, é preenchido no foreach abaixo
// vou usar este array em um implode depois para facilitar o uso da vírgula que separa cada coluna
$columnsSql = [];

foreach ($tabelas as $tabela => $colunas) {  
    foreach ($colunas as $coluna) {
        $colunaDB      = $tabela.'.'.$coluna; // é a coluna com prefixo da tabela
        $colunaApelido = $tabela.'_'.$coluna; // é a coluna com apelido, para você poder pegar depois no while

        $columnsSql[] = $colunaDB.' AS '.$colunaApelido
    }
}

$sql = BD::conn()->prepare(
    "SELECT ".implode(', ', $columnsSql)."
    FROM tabela_a a
    LEFT JOIN tabela b ON a.campo = b.campo"
);

UPDATING

According to the documentation on the PDO connection you can set the attribute PDO::ATTR_FETCH_TABLE_NAMES for:

Uses the table name as prefix in each column name returned in the result set. The table name and column name are separated by a decimal character (.). Support for this attribute is at driver level; it may not be supported by your driver.

Credits: that answer and this one.

  • If they are tables with many columns, there is no easier solution?

  • @Leoletto Unfortunately not, unless you want to change all your query manually so that every column prefixes the table name.

  • Is there a reference link or could you help me understand how I can do this?

  • 1

    @Leoletto edited the answer with the code that adds the table as a prefix, see if it helps you.

  • @Leoletto updated the answer with a much more practical option, take a look please and see if it works.

1

You can create aliases for your fields in your select, so they would be assigned names, e.g.:

SELECT a.campo1 as campo1A, a.campo2 as campo2A, a.data as dataA, b.data as dataB
FROM tabela_a a
LEFT JOIN tabela b ON
a.campo = b.campo

Browser other questions tagged

You are not signed in. Login or sign up in order to post.