MySQL UNION查询中的相同行名称

I'm building a simple php search engine that will search in multiple tables. Some tables have the same column name so I started using "AS" to identify each one.

Here's the query that I'm using:

$query = " (SELECT coluna1 as txt1_festival, coluna2 as txt2_festival, 'festival' as tabela FROM tb_festival WHERE coluna1 LIKE '%" . $buscar . "%' OR coluna2 LIKE '%" . $buscar ."%') 
    UNION
(SELECT pergunta, resposta, 'faqs' as tabela FROM tb_faqs WHERE pergunta LIKE '%" . $buscar . "%' OR resposta LIKE '%" . $buscar ."%')";

The problem is that I'm getting all results with the same column names txt1_festival and txt2_festival, even when the result comes from the second table which columns names are pergunta and resposta.

Can anyone tell me what should I do to achieve it?!

If I have understood correctly what you want...

You may use something like this:

$query = "
    (SELECT coluna1 as txt1_festival, coluna2 as txt2_festival, null as pergunta, null as resposta, 'festival' as tabela FROM tb_festival WHERE coluna1 LIKE '%" . $buscar . "%' OR coluna2 LIKE '%" . $buscar ."%') 
    UNION
    (SELECT null as txt1_festival, null as txt2_festival, pergunta, resposta, 'faqs' as tabela FROM tb_faqs WHERE pergunta LIKE '%" . $buscar . "%' OR resposta LIKE '%" . $buscar ."%')
";

But IMHO this is a weird way to do the things. If you have to search for something in several tables (which structure and number of columns may vary), better just run several queries.


The fact is that "structure" (i.e. number of columns, their names and types) of query result must be determinable without executing the query.

I.e. suppose that you have table tbl1 with fields (id integer, creation_time timestamp, val1 text, val2 text) and are going to execute query SELECT id, id+2 as id_plus_2, creation_time AS cr_time FROM tbl1. Without even executing the query, RDBMS will understand that resulting structure should be (id integer, id_plus_2 integer, cr_time timestamp).

Therefore you cannot do for example stuff like this:

SELECT id, val1 AS 〈I_wanna_name_this_column_as_qq_if_id_is_less_than_17_and_as_pp_otherwise〉, val2 FROM tbl1;

or:

SELECT id, val1, val2 AS 〈I_wanna_name_this_column_as_qq_if_today_is_tuesday_and_as_pp_otherwise〉 FROM tbl1;

The same with UNION-using queries. RDMBS must know structure of the UNION-query result just after reading the query (assuming it already knows structures of tables). Therefore, even before executing the UNION-query:

  • RDMBS tries to determine number of columns that the whole UNION-query will return (by looking on numbers of columns that specific SELECT-queries are expected to return). If two SELECT-queries in the UNION-query are expected to return different number of columns — it's error.
  • RDMBS tries to determine types of columns that the whole UNION-query will return (by looking on types of columns that specific SELECT-queries are expected to return). If types of corresponding columns in two SELECT-queries in the UNION-query are too different (that RDBMS cannot cast them to common supertype) — it's error.
  • RDMBS tries to determine names of columns that the whole UNION-query will return (by looking on names of columns that specific SELECT-queries are expected to return). If names of corresponding columns in two SELECT-queries in the UNION-query are different — it's not so important, RDBMS takes first one. (Theoretically, it's not so important, and designed-in-another-way RDBMS would take the second one, or even combine them in some way — but the fact is that all collumn names must be known without executing the query.)

It's the consequence of using UNION operator — it names the columns by the names of the first table in query. Please see the documentation